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.
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
|
@ -43,8 +48,18 @@ public interface AuthenticationProvider {
|
|||
throws AuthenticationException;
|
||||
|
||||
/**
|
||||
* Returns true if this <Code>AuthenticationProvider</code> supports the
|
||||
* indicated <Code>Authentication</code> object.
|
||||
* Returns <code>true</code> if this <Code>AuthenticationProvider</code>
|
||||
* 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>
|
||||
* Selection of an <code>AuthenticationProvider</code> capable of
|
||||
|
@ -52,7 +67,8 @@ public interface AuthenticationProvider {
|
|||
* <code>ProviderManager</code>.
|
||||
* </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);
|
||||
}
|
||||
|
|
|
@ -123,7 +123,11 @@ public class ProviderManager implements InitializingBean, AuthenticationManager
|
|||
logger.debug("Authentication attempt using "
|
||||
+ 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());
|
||||
}
|
||||
|
||||
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()
|
||||
throws Exception {
|
||||
List providers = new Vector();
|
||||
|
@ -146,6 +166,19 @@ public class ProviderManagerTests extends TestCase {
|
|||
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 ==========================================================
|
||||
|
||||
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…
Reference in New Issue