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:
Ben Alex 2004-04-18 12:03:07 +00:00
parent a6b5b8d828
commit 872ace9164
3 changed files with 79 additions and 5 deletions

View File

@ -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);
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}
}