diff --git a/core/src/main/java/org/springframework/security/authentication/AbstractAuthenticationManager.java b/core/src/main/java/org/springframework/security/authentication/AbstractAuthenticationManager.java deleted file mode 100644 index 5574ebb7c4..0000000000 --- a/core/src/main/java/org/springframework/security/authentication/AbstractAuthenticationManager.java +++ /dev/null @@ -1,84 +0,0 @@ -/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.authentication; - -import org.springframework.security.core.Authentication; -import org.springframework.security.core.AuthenticationException; - -/** - * An abstract implementation of the {@link AuthenticationManager}. - * - * @author Wesley Hall - */ -public abstract class AbstractAuthenticationManager implements AuthenticationManager { - - //~ Instance fields ================================================================================================ - private boolean clearExtraInformation = false; - - //~ Methods ======================================================================================================== - - /** - * An implementation of the authenticate method that calls the abstract method - * doAuthenticatation to do its work. - *

- * If doAuthenticate throws an AuthenticationException then the exception is populated - * with the failed Authentication object that failed. - * - * @param authRequest the authentication request object - * - * @return a fully authenticated object including credentials - * - * @throws AuthenticationException if authentication fails - */ - public final Authentication authenticate(Authentication authRequest) throws AuthenticationException { - try { - return doAuthentication(authRequest); - } catch (AuthenticationException e) { - e.setAuthentication(authRequest); - - if (clearExtraInformation) { - e.clearExtraInformation(); - } - - throw e; - } - } - - /** - * Concrete implementations of this class override this method to provide the authentication service. - *

- * The contract for this method is documented in the - * {@link AuthenticationManager#authenticate(Authentication)}. - * - * @param authentication the authentication request object - * - * @return a fully authenticated object including credentials - * - * @throws AuthenticationException if authentication fails - */ - protected abstract Authentication doAuthentication(Authentication authentication) throws AuthenticationException; - - /** - * If set to true, the extraInformation set on an AuthenticationException will be cleared - * before rethrowing it. This is useful for use with remoting protocols where the information shouldn't - * be serialized to the client. Defaults to 'false'. - * - * @see org.springframework.security.core.AuthenticationException#getExtraInformation() - */ - public void setClearExtraInformation(boolean clearExtraInformation) { - this.clearExtraInformation = clearExtraInformation; - } -} diff --git a/core/src/main/java/org/springframework/security/authentication/ProviderManager.java b/core/src/main/java/org/springframework/security/authentication/ProviderManager.java index 9117bb1109..55badc8879 100644 --- a/core/src/main/java/org/springframework/security/authentication/ProviderManager.java +++ b/core/src/main/java/org/springframework/security/authentication/ProviderManager.java @@ -65,7 +65,7 @@ import org.springframework.util.Assert; * * @see DefaultAuthenticationEventPublisher */ -public class ProviderManager extends AbstractAuthenticationManager implements MessageSourceAware, InitializingBean { +public class ProviderManager implements AuthenticationManager, MessageSourceAware, InitializingBean { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(ProviderManager.class); @@ -77,6 +77,8 @@ public class ProviderManager extends AbstractAuthenticationManager implements Me protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); private AuthenticationManager parent; + private boolean clearExtraInformation = false; + //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { @@ -104,17 +106,20 @@ public class ProviderManager extends AbstractAuthenticationManager implements Me * * @throws AuthenticationException if authentication fails. */ - public Authentication doAuthentication(Authentication authentication) throws AuthenticationException { + public Authentication authenticate(Authentication authentication) throws AuthenticationException { Class toTest = authentication.getClass(); AuthenticationException lastException = null; Authentication result = null; + boolean debug = logger.isDebugEnabled(); for (AuthenticationProvider provider : getProviders()) { if (!provider.supports(toTest)) { continue; } - logger.debug("Authentication attempt using " + provider.getClass().getName()); + if (debug) { + logger.debug("Authentication attempt using " + provider.getClass().getName()); + } try { result = provider.authenticate(authentication); @@ -124,8 +129,8 @@ public class ProviderManager extends AbstractAuthenticationManager implements Me break; } } catch (AccountStatusException e) { + prepareException(e, authentication); // SEC-546: Avoid polling additional providers if auth failure is due to invalid account status - eventPublisher.publishAuthenticationFailure(e, authentication); throw e; } catch (AuthenticationException e) { lastException = e; @@ -157,10 +162,19 @@ public class ProviderManager extends AbstractAuthenticationManager implements Me } eventPublisher.publishAuthenticationFailure(lastException, authentication); + prepareException(lastException, authentication); throw lastException; } + private void prepareException(AuthenticationException ex, Authentication auth) { + ex.setAuthentication(auth); + + if (clearExtraInformation) { + ex.clearExtraInformation(); + } + } + /** * Copies the authentication details from a source Authentication object to a destination one, provided the * latter does not already have one set. @@ -211,6 +225,17 @@ public class ProviderManager extends AbstractAuthenticationManager implements Me this.providers = providers; } + /** + * If set to true, the extraInformation set on an AuthenticationException will be cleared + * before rethrowing it. This is useful for use with remoting protocols where the information shouldn't + * be serialized to the client. Defaults to 'false'. + * + * @see org.springframework.security.core.AuthenticationException#getExtraInformation() + */ + public void setClearExtraInformation(boolean clearExtraInformation) { + this.clearExtraInformation = clearExtraInformation; + } + private static final class NullEventPublisher implements AuthenticationEventPublisher { public void publishAuthenticationFailure(AuthenticationException exception, Authentication authentication) {} public void publishAuthenticationSuccess(Authentication authentication) {} diff --git a/core/src/main/java/org/springframework/security/authentication/rcp/RemoteAuthenticationManagerImpl.java b/core/src/main/java/org/springframework/security/authentication/rcp/RemoteAuthenticationManagerImpl.java index 528f1a81ce..90b00bc89c 100644 --- a/core/src/main/java/org/springframework/security/authentication/rcp/RemoteAuthenticationManagerImpl.java +++ b/core/src/main/java/org/springframework/security/authentication/rcp/RemoteAuthenticationManagerImpl.java @@ -57,7 +57,7 @@ public class RemoteAuthenticationManagerImpl implements RemoteAuthenticationMana } } - public AuthenticationManager getAuthenticationManager() { + protected AuthenticationManager getAuthenticationManager() { return authenticationManager; } diff --git a/core/src/test/java/org/springframework/security/MockAuthenticationManager.java b/core/src/test/java/org/springframework/security/MockAuthenticationManager.java deleted file mode 100644 index 0d5dcf3600..0000000000 --- a/core/src/test/java/org/springframework/security/MockAuthenticationManager.java +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security; - -import org.springframework.security.authentication.AbstractAuthenticationManager; -import org.springframework.security.authentication.BadCredentialsException; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.AuthenticationException; - -/** - * Simply accepts as valid whatever is passed to it, if grantAccess is set to true. - * - * @author Ben Alex - * @author Wesley Hall - */ -public class MockAuthenticationManager extends AbstractAuthenticationManager { - //~ Instance fields ================================================================================================ - - private boolean grantAccess = true; - - //~ Constructors =================================================================================================== - - public MockAuthenticationManager(boolean grantAccess) { - this.grantAccess = grantAccess; - } - - public MockAuthenticationManager() { - } - - //~ Methods ======================================================================================================== - - public Authentication doAuthentication(Authentication authentication) throws AuthenticationException { - if (grantAccess) { - return authentication; - } else { - throw new BadCredentialsException("MockAuthenticationManager instructed to deny access"); - } - } -} diff --git a/core/src/test/java/org/springframework/security/authentication/rcp/RemoteAuthenticationManagerImplTests.java b/core/src/test/java/org/springframework/security/authentication/rcp/RemoteAuthenticationManagerImplTests.java index 4a6ddd478c..5da7784d2e 100644 --- a/core/src/test/java/org/springframework/security/authentication/rcp/RemoteAuthenticationManagerImplTests.java +++ b/core/src/test/java/org/springframework/security/authentication/rcp/RemoteAuthenticationManagerImplTests.java @@ -15,11 +15,15 @@ package org.springframework.security.authentication.rcp; -import junit.framework.TestCase; +import static org.junit.Assert.*; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; -import org.springframework.security.MockAuthenticationManager; -import org.springframework.security.authentication.rcp.RemoteAuthenticationException; -import org.springframework.security.authentication.rcp.RemoteAuthenticationManagerImpl; +import org.junit.Test; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.TestingAuthenticationToken; +import org.springframework.security.core.Authentication; /** @@ -27,27 +31,20 @@ import org.springframework.security.authentication.rcp.RemoteAuthenticationManag * * @author Ben Alex */ -public class RemoteAuthenticationManagerImplTests extends TestCase { +public class RemoteAuthenticationManagerImplTests { //~ Methods ======================================================================================================== + @Test(expected=RemoteAuthenticationException.class) public void testFailedAuthenticationReturnsRemoteAuthenticationException() { RemoteAuthenticationManagerImpl manager = new RemoteAuthenticationManagerImpl(); - manager.setAuthenticationManager(new MockAuthenticationManager(false)); + AuthenticationManager am = mock(AuthenticationManager.class); + when(am.authenticate(any(Authentication.class))).thenThrow(new BadCredentialsException("")); + manager.setAuthenticationManager(am); - try { - manager.attemptAuthentication("rod", "password"); - fail("Should have thrown RemoteAuthenticationException"); - } catch (RemoteAuthenticationException expected) { - assertTrue(true); - } - } - - public void testGettersSetters() { - RemoteAuthenticationManagerImpl manager = new RemoteAuthenticationManagerImpl(); - manager.setAuthenticationManager(new MockAuthenticationManager(true)); - assertNotNull(manager.getAuthenticationManager()); + manager.attemptAuthentication("rod", "password"); } + @Test public void testStartupChecksAuthenticationManagerSet() throws Exception { RemoteAuthenticationManagerImpl manager = new RemoteAuthenticationManagerImpl(); @@ -55,17 +52,19 @@ public class RemoteAuthenticationManagerImplTests extends TestCase { manager.afterPropertiesSet(); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { - assertTrue(true); } - manager.setAuthenticationManager(new MockAuthenticationManager(true)); + manager.setAuthenticationManager(mock(AuthenticationManager.class)); manager.afterPropertiesSet(); assertTrue(true); } + @Test public void testSuccessfulAuthentication() { RemoteAuthenticationManagerImpl manager = new RemoteAuthenticationManagerImpl(); - manager.setAuthenticationManager(new MockAuthenticationManager(true)); + AuthenticationManager am = mock(AuthenticationManager.class); + when(am.authenticate(any(Authentication.class))).thenReturn(new TestingAuthenticationToken("u","p","A")); + manager.setAuthenticationManager(am); manager.attemptAuthentication("rod", "password"); } diff --git a/core/src/test/java/org/springframework/security/provisioning/JdbcUserDetailsManagerTests.java b/core/src/test/java/org/springframework/security/provisioning/JdbcUserDetailsManagerTests.java index 776aae3853..58e980e486 100644 --- a/core/src/test/java/org/springframework/security/provisioning/JdbcUserDetailsManagerTests.java +++ b/core/src/test/java/org/springframework/security/provisioning/JdbcUserDetailsManagerTests.java @@ -1,6 +1,7 @@ package org.springframework.security.provisioning; import static org.junit.Assert.*; +import static org.mockito.Mockito.*; import java.util.Collections; import java.util.HashMap; @@ -13,10 +14,10 @@ import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.security.MockAuthenticationManager; import org.springframework.security.PopulatedDatabase; import org.springframework.security.TestDataSource; import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; @@ -155,7 +156,10 @@ public class JdbcUserDetailsManagerTests { public void changePasswordSucceedsWithIfReAuthenticationSucceeds() { insertJoe(); Authentication currentAuth = authenticateJoe(); - manager.setAuthenticationManager(new MockAuthenticationManager(true)); + AuthenticationManager am = mock(AuthenticationManager.class); + when(am.authenticate(currentAuth)).thenReturn(currentAuth); + + manager.setAuthenticationManager(am); manager.changePassword("password", "newPassword"); UserDetails newJoe = manager.loadUserByUsername("joe"); @@ -172,7 +176,10 @@ public class JdbcUserDetailsManagerTests { public void changePasswordFailsIfReAuthenticationFails() { insertJoe(); authenticateJoe(); - manager.setAuthenticationManager(new MockAuthenticationManager(false)); + AuthenticationManager am = mock(AuthenticationManager.class); + when(am.authenticate(any(Authentication.class))).thenThrow(new BadCredentialsException("")); + + manager.setAuthenticationManager(am); try { manager.changePassword("password", "newPassword");