mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-06-24 21:12:18 +00:00
Modify contract of AuthenticationProvider to allow AuthenticationProvider implementations to return null if they do not wish to process a given Authentication request, despite asserting they support it.
This commit is contained in:
parent
a6b5b8d828
commit
872ace9164
@ -35,7 +35,12 @@ public interface AuthenticationProvider {
|
|||||||
*
|
*
|
||||||
* @param authentication the authentication request object.
|
* @param authentication the authentication request object.
|
||||||
*
|
*
|
||||||
* @return a fully authenticated object including credentials.
|
* @return a fully authenticated object including credentials. May return
|
||||||
|
* <code>null</code> if the <code>AuthenticationProvider</code> is
|
||||||
|
* unable to support authentication of the passed
|
||||||
|
* <code>Authentication</code> object. In such a case, the next
|
||||||
|
* <code>AuthenticationProvider</code> that supports the presented
|
||||||
|
* <code>Authentication</code> class will be tried.
|
||||||
*
|
*
|
||||||
* @throws AuthenticationException if authentication fails.
|
* @throws AuthenticationException if authentication fails.
|
||||||
*/
|
*/
|
||||||
@ -43,8 +48,18 @@ public interface AuthenticationProvider {
|
|||||||
throws AuthenticationException;
|
throws AuthenticationException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this <Code>AuthenticationProvider</code> supports the
|
* Returns <code>true</code> if this <Code>AuthenticationProvider</code>
|
||||||
* indicated <Code>Authentication</code> object.
|
* supports the indicated <Code>Authentication</code> object.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Returning <code>true</code> does not guarantee an
|
||||||
|
* <code>AuthenticationProvider</code> will be able to authenticate the
|
||||||
|
* presented instance of the <code>Authentication</code> class. It simply
|
||||||
|
* indicates it can support closer evaluation of it. An
|
||||||
|
* <code>AuthenticationProvider</code> can still return <code>null</code>
|
||||||
|
* from the {@link #authenticate(Authentication)} method to indicate
|
||||||
|
* another <code>AuthenticationProvider</code> should be tried.
|
||||||
|
* </p>
|
||||||
*
|
*
|
||||||
* <P>
|
* <P>
|
||||||
* Selection of an <code>AuthenticationProvider</code> capable of
|
* Selection of an <code>AuthenticationProvider</code> capable of
|
||||||
@ -52,7 +67,8 @@ public interface AuthenticationProvider {
|
|||||||
* <code>ProviderManager</code>.
|
* <code>ProviderManager</code>.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @return DOCUMENT ME!
|
* @return <code>true</code> if the implementation can more closely
|
||||||
|
* evaluate the <code>Authentication</code> class presented
|
||||||
*/
|
*/
|
||||||
public boolean supports(Class authentication);
|
public boolean supports(Class authentication);
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,11 @@ public class ProviderManager implements InitializingBean, AuthenticationManager
|
|||||||
logger.debug("Authentication attempt using "
|
logger.debug("Authentication attempt using "
|
||||||
+ provider.getClass().getName());
|
+ provider.getClass().getName());
|
||||||
|
|
||||||
return provider.authenticate(authentication);
|
Authentication result = provider.authenticate(authentication);
|
||||||
|
|
||||||
|
if (result != null) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,6 +90,26 @@ public class ProviderManagerTests extends TestCase {
|
|||||||
assertEquals("ROLE_TWO", castResult.getAuthorities()[1].getAuthority());
|
assertEquals("ROLE_TWO", castResult.getAuthorities()[1].getAuthority());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testAuthenticationSuccessWhenFirstProviderReturnsNullButSecondAuthenticates() {
|
||||||
|
TestingAuthenticationToken token = new TestingAuthenticationToken("Test",
|
||||||
|
"Password",
|
||||||
|
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
|
||||||
|
"ROLE_TWO")});
|
||||||
|
|
||||||
|
ProviderManager mgr = makeProviderManagerWithMockProviderWhichReturnsNullInList();
|
||||||
|
Authentication result = mgr.authenticate(token);
|
||||||
|
|
||||||
|
if (!(result instanceof TestingAuthenticationToken)) {
|
||||||
|
fail("Should have returned instance of TestingAuthenticationToken");
|
||||||
|
}
|
||||||
|
|
||||||
|
TestingAuthenticationToken castResult = (TestingAuthenticationToken) result;
|
||||||
|
assertEquals("Test", castResult.getPrincipal());
|
||||||
|
assertEquals("Password", castResult.getCredentials());
|
||||||
|
assertEquals("ROLE_ONE", castResult.getAuthorities()[0].getAuthority());
|
||||||
|
assertEquals("ROLE_TWO", castResult.getAuthorities()[1].getAuthority());
|
||||||
|
}
|
||||||
|
|
||||||
public void testStartupFailsIfProviderListDoesNotContainingProviders()
|
public void testStartupFailsIfProviderListDoesNotContainingProviders()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
List providers = new Vector();
|
List providers = new Vector();
|
||||||
@ -146,6 +166,19 @@ public class ProviderManagerTests extends TestCase {
|
|||||||
return mgr;
|
return mgr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ProviderManager makeProviderManagerWithMockProviderWhichReturnsNullInList() {
|
||||||
|
MockProviderWhichReturnsNull provider1 = new MockProviderWhichReturnsNull();
|
||||||
|
MockProvider provider2 = new MockProvider();
|
||||||
|
List providers = new Vector();
|
||||||
|
providers.add(provider1);
|
||||||
|
providers.add(provider2);
|
||||||
|
|
||||||
|
ProviderManager mgr = new ProviderManager();
|
||||||
|
mgr.setProviders(providers);
|
||||||
|
|
||||||
|
return mgr;
|
||||||
|
}
|
||||||
|
|
||||||
//~ Inner Classes ==========================================================
|
//~ Inner Classes ==========================================================
|
||||||
|
|
||||||
private class MockProvider implements AuthenticationProvider {
|
private class MockProvider implements AuthenticationProvider {
|
||||||
@ -168,4 +201,25 @@ public class ProviderManagerTests extends TestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class MockProviderWhichReturnsNull implements AuthenticationProvider {
|
||||||
|
public Authentication authenticate(Authentication authentication)
|
||||||
|
throws AuthenticationException {
|
||||||
|
if (supports(authentication.getClass())) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
throw new AuthenticationServiceException(
|
||||||
|
"Don't support this class");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean supports(Class authentication) {
|
||||||
|
if (TestingAuthenticationToken.class.isAssignableFrom(
|
||||||
|
authentication)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user