diff --git a/config/src/test/java/org/springframework/security/config/authentication/AuthenticationManagerBeanDefinitionParserTests.java b/config/src/test/java/org/springframework/security/config/authentication/AuthenticationManagerBeanDefinitionParserTests.java index 619295c297..c488d8acf1 100644 --- a/config/src/test/java/org/springframework/security/config/authentication/AuthenticationManagerBeanDefinitionParserTests.java +++ b/config/src/test/java/org/springframework/security/config/authentication/AuthenticationManagerBeanDefinitionParserTests.java @@ -1,14 +1,10 @@ package org.springframework.security.config.authentication; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; import org.junit.Test; -import org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException; import org.springframework.context.support.AbstractXmlApplicationContext; import org.springframework.security.authentication.AuthenticationProvider; -import org.springframework.security.authentication.concurrent.ConcurrentSessionControllerImpl; -import org.springframework.security.authentication.concurrent.SessionRegistryImpl; -import org.springframework.security.config.BeanIds; import org.springframework.security.config.util.InMemoryXmlApplicationContext; /** @@ -19,13 +15,6 @@ import org.springframework.security.config.util.InMemoryXmlApplicationContext; public class AuthenticationManagerBeanDefinitionParserTests { private AbstractXmlApplicationContext appContext; - private final String SESSION_CONTROLLER = - "" + - " " + - " " + - " " + - ""; - @Test // SEC-1225 public void providersAreRegisteredAsTopLevelBeans() throws Exception { @@ -36,23 +25,10 @@ public class AuthenticationManagerBeanDefinitionParserTests { " " + " " + " " + - "" + SESSION_CONTROLLER, "3.0"); + "", "3.0"); assertEquals(1, appContext.getBeansOfType(AuthenticationProvider.class).size()); } - @Test(expected=XmlBeanDefinitionStoreException.class) - public void sessionControllerRefAttributeIsRejectedFor30Context() throws Exception { - setContext( - "" + - " " + - " " + - " " + - " " + - " " + - "" + SESSION_CONTROLLER, "3.0"); - appContext.getBean(BeanIds.AUTHENTICATION_MANAGER); - } - private void setContext(String context, String version) { appContext = new InMemoryXmlApplicationContext(context, version, null); } diff --git a/core/src/main/java/org/springframework/security/authentication/DefaultAuthenticationEventPublisher.java b/core/src/main/java/org/springframework/security/authentication/DefaultAuthenticationEventPublisher.java index 2ea9f955d5..6732e40420 100644 --- a/core/src/main/java/org/springframework/security/authentication/DefaultAuthenticationEventPublisher.java +++ b/core/src/main/java/org/springframework/security/authentication/DefaultAuthenticationEventPublisher.java @@ -8,10 +8,8 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; -import org.springframework.security.authentication.concurrent.ConcurrentLoginException; import org.springframework.security.authentication.event.AbstractAuthenticationEvent; import org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent; -import org.springframework.security.authentication.event.AuthenticationFailureConcurrentLoginEvent; import org.springframework.security.authentication.event.AuthenticationFailureCredentialsExpiredEvent; import org.springframework.security.authentication.event.AuthenticationFailureDisabledEvent; import org.springframework.security.authentication.event.AuthenticationFailureExpiredEvent; @@ -70,8 +68,6 @@ public class DefaultAuthenticationEventPublisher implements AuthenticationEventP AuthenticationFailureBadCredentialsEvent.class.getName()); exceptionMappings.put(UsernameNotFoundException.class.getName(), AuthenticationFailureBadCredentialsEvent.class.getName()); - exceptionMappings.put(ConcurrentLoginException.class.getName(), - AuthenticationFailureConcurrentLoginEvent.class.getName()); exceptionMappings.put(ProviderNotFoundException.class.getName(), AuthenticationFailureProviderNotFoundEvent.class.getName()); exceptionMappings.put("org.springframework.security.authentication.cas.ProxyUntrustedException", 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 ce15a15f1f..c313d07d63 100644 --- a/core/src/main/java/org/springframework/security/authentication/ProviderManager.java +++ b/core/src/main/java/org/springframework/security/authentication/ProviderManager.java @@ -24,8 +24,6 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; -import org.springframework.security.authentication.concurrent.ConcurrentLoginException; -import org.springframework.security.authentication.concurrent.ConcurrentSessionController; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.SpringSecurityMessageSource; @@ -35,8 +33,6 @@ import org.springframework.util.Assert; /** * Iterates an {@link Authentication} request through a list of {@link AuthenticationProvider}s. * - * Can optionally be configured with a {@link ConcurrentSessionController} to limit the number of sessions a user can - * have. *

* AuthenticationProviders are usually tried in order until one provides a non-null response. * A non-null response indicates the provider had authority to decide on the authentication request and no further @@ -47,9 +43,8 @@ import org.springframework.util.Assert; * If no provider returns a non-null response, or indicates it can even process an Authentication, * the ProviderManager will throw a ProviderNotFoundException. *

- * The exception to this process is when a provider throws an {@link AccountStatusException} or if the configured - * concurrent session controller throws a {@link ConcurrentLoginException}. In both these cases, no further providers - * in the list will be queried. + * The exception to this process is when a provider throws an {@link AccountStatusException}, in which case no + * further providers in the list will be queried. * *

Event Publishing

*

@@ -68,7 +63,7 @@ import org.springframework.util.Assert; * @author Ben Alex * @author Luke Taylor * @version $Id$ - * @see ConcurrentSessionController + * * @see DefaultAuthenticationEventPublisher */ public class ProviderManager extends AbstractAuthenticationManager implements MessageSourceAware, InitializingBean { @@ -79,7 +74,6 @@ public class ProviderManager extends AbstractAuthenticationManager implements Me //~ Instance fields ================================================================================================ private AuthenticationEventPublisher eventPublisher = new NullEventPublisher(); - private ConcurrentSessionController sessionController = new NullConcurrentSessionController(); private List providers = Collections.emptyList(); protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); private AuthenticationManager parent; @@ -151,20 +145,12 @@ public class ProviderManager extends AbstractAuthenticationManager implements Me } } - // Finally check if the concurrent session controller will allow authentication - try { - if (result != null) { - sessionController.checkAuthenticationAllowed(result); - sessionController.registerSuccessfulAuthentication(result); - eventPublisher.publishAuthenticationSuccess(result); - - return result; - } - } catch (AuthenticationException e) { - lastException = e; + if (result != null) { + eventPublisher.publishAuthenticationSuccess(result); + return result; } - // Session control failed, parent was null, or didn't authenticate (or throw an exception). + // Parent was null, or didn't authenticate (or throw an exception). if (lastException == null) { lastException = new ProviderNotFoundException(messages.getMessage("ProviderManager.providerNotFound", @@ -199,16 +185,6 @@ public class ProviderManager extends AbstractAuthenticationManager implements Me return providers; } - /** - * The configured {@link ConcurrentSessionController} is returned or the {@link - * NullConcurrentSessionController} if a specific one has not been set. - * - * @return {@link ConcurrentSessionController} instance - */ - ConcurrentSessionController getSessionController() { - return sessionController; - } - public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } @@ -239,22 +215,8 @@ public class ProviderManager extends AbstractAuthenticationManager implements Me this.providers = providers; } - /** - * Set the {@link ConcurrentSessionController} to be used for limiting users' sessions. - * - * @param sessionController {@link ConcurrentSessionController} - */ - public void setSessionController(ConcurrentSessionController sessionController) { - this.sessionController = sessionController; - } - private static final class NullEventPublisher implements AuthenticationEventPublisher { public void publishAuthenticationFailure(AuthenticationException exception, Authentication authentication) {} public void publishAuthenticationSuccess(Authentication authentication) {} } - - private static final class NullConcurrentSessionController implements ConcurrentSessionController { - public void checkAuthenticationAllowed(Authentication request) {} - public void registerSuccessfulAuthentication(Authentication authentication) {} - } } diff --git a/core/src/main/java/org/springframework/security/authentication/concurrent/ConcurrentLoginException.java b/core/src/main/java/org/springframework/security/authentication/concurrent/ConcurrentLoginException.java deleted file mode 100644 index ca5632735b..0000000000 --- a/core/src/main/java/org/springframework/security/authentication/concurrent/ConcurrentLoginException.java +++ /dev/null @@ -1,34 +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.concurrent; - -import org.springframework.security.core.AuthenticationException; - - -/** - * Thrown by ConcurrentSessionControllerImpl if an attempt is made to login and the user has already - * exceeded their maxmimum allowed sessions. - * - * @author Ben Alex - * @version $Id$ - */ -public class ConcurrentLoginException extends AuthenticationException { - //~ Constructors =================================================================================================== - - public ConcurrentLoginException(String msg) { - super(msg); - } -} diff --git a/core/src/main/java/org/springframework/security/authentication/concurrent/ConcurrentSessionControllerImpl.java b/core/src/main/java/org/springframework/security/authentication/concurrent/ConcurrentSessionControllerImpl.java deleted file mode 100644 index 18699ce03c..0000000000 --- a/core/src/main/java/org/springframework/security/authentication/concurrent/ConcurrentSessionControllerImpl.java +++ /dev/null @@ -1,174 +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.concurrent; - -import java.util.List; - -import org.springframework.security.core.Authentication; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.core.SpringSecurityMessageSource; - -import org.springframework.beans.factory.InitializingBean; - -import org.springframework.context.MessageSource; -import org.springframework.context.MessageSourceAware; -import org.springframework.context.support.MessageSourceAccessor; - -import org.springframework.util.Assert; - - -/** - * Base implementation of {@link ConcurrentSessionControllerImpl} which prohibits simultaneous logins. - * - * @author Ben Alex - * @version $Id$ - */ -public class ConcurrentSessionControllerImpl implements ConcurrentSessionController, InitializingBean, - MessageSourceAware { - //~ Instance fields ================================================================================================ - - protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); - private SessionRegistry sessionRegistry; - private boolean exceptionIfMaximumExceeded = false; - private int maximumSessions = 1; - - //~ Methods ======================================================================================================== - - public void afterPropertiesSet() throws Exception { - Assert.notNull(sessionRegistry, "SessionRegistry required"); - Assert.isTrue(maximumSessions != 0, - "MaximumLogins must be either -1 to allow unlimited logins, or a positive integer to specify a maximum"); - Assert.notNull(this.messages, "A message source must be set"); - } - - public void checkAuthenticationAllowed(Authentication request) throws AuthenticationException { - Assert.notNull(request, "Authentication request cannot be null (violation of interface contract)"); - - String sessionId = obtainSessionId(request); - - final List sessions = sessionRegistry.getAllSessions(request.getPrincipal(), false); - - int sessionCount = sessions == null ? 0 : sessions.size(); - - int allowableSessions = getMaximumSessionsForThisUser(request); - Assert.isTrue(allowableSessions != 0, "getMaximumSessionsForThisUser() must return either -1 to allow " - + "unlimited logins, or a positive integer to specify a maximum"); - - if (sessionCount < allowableSessions) { - // They haven't got too many login sessions running at present - return; - } - - if (allowableSessions == -1) { - // We permit unlimited logins - return; - } - - if (sessionCount == allowableSessions) { - // Only permit it though if this request is associated with one of the sessions - for (SessionInformation si : sessions) { - if (si.getSessionId().equals(sessionId)) { - return; - } - } - } - - allowableSessionsExceeded(sessionId, sessions, allowableSessions, sessionRegistry); - } - - /** - * Allows subclasses to customise behaviour when too many sessions are detected. - * - * @param sessionId the session ID of the present request - * @param sessions either null or all unexpired sessions associated with the principal - * @param allowableSessions the number of concurrent sessions the user is allowed to have - * @param registry an instance of the SessionRegistry for subclass use - * - * @throws ConcurrentLoginException if the - */ - protected void allowableSessionsExceeded(String sessionId, List sessions, int allowableSessions, - SessionRegistry registry) { - if (exceptionIfMaximumExceeded || (sessions == null)) { - throw new ConcurrentLoginException(messages.getMessage("ConcurrentSessionControllerImpl.exceededAllowed", - new Object[] {new Integer(allowableSessions)}, - "Maximum sessions of {0} for this principal exceeded")); - } - - // Determine least recently used session, and mark it for invalidation - SessionInformation leastRecentlyUsed = null; - - for (int i = 0; i < sessions.size(); i++) { - if ((leastRecentlyUsed == null) - || sessions.get(i).getLastRequest().before(leastRecentlyUsed.getLastRequest())) { - leastRecentlyUsed = sessions.get(i); - } - } - - leastRecentlyUsed.expireNow(); - } - - public void registerSuccessfulAuthentication(Authentication authentication) { - Assert.notNull(authentication, "Authentication cannot be null (violation of interface contract)"); - - sessionRegistry.registerNewSession(obtainSessionId(authentication), authentication.getPrincipal()); - } - - /** - * Method intended for use by subclasses to override the maximum number of sessions that are permitted for - * a particular authentication. The default implementation simply returns the maximumSessions value - * for the bean. - * - * @param authentication to determine the maximum sessions for - * - * @return either -1 meaning unlimited, or a positive integer to limit (never zero) - */ - protected int getMaximumSessionsForThisUser(Authentication authentication) { - return maximumSessions; - } - - public void setExceptionIfMaximumExceeded(boolean exceptionIfMaximumExceeded) { - this.exceptionIfMaximumExceeded = exceptionIfMaximumExceeded; - } - - public void setMaximumSessions(int maximumSessions) { - this.maximumSessions = maximumSessions; - } - - public void setMessageSource(MessageSource messageSource) { - this.messages = new MessageSourceAccessor(messageSource); - } - - public void setSessionRegistry(SessionRegistry sessionRegistry) { - this.sessionRegistry = sessionRegistry; - } - - public SessionRegistry getSessionRegistry() { - return sessionRegistry; - } - - private String obtainSessionId(Authentication auth) { - if (auth.getDetails() == null || !(auth.getDetails() instanceof SessionIdentifierAware)) { - throw new IllegalArgumentException("The 'details' property of the supplied Authentication " + - "object must be set and must implement 'SessionIdentifierAware', but Authentication.getDetails() " + - "returned " + auth.getDetails()); - } - - String sessionId = ((SessionIdentifierAware) auth.getDetails()).getSessionId(); - Assert.hasText(sessionId, "SessionIdentifierAware did not return a Session ID (" + auth.getDetails() + ")"); - - return sessionId; - } -} diff --git a/core/src/main/java/org/springframework/security/authentication/concurrent/NullConcurrentSessionController.java b/core/src/main/java/org/springframework/security/authentication/concurrent/NullConcurrentSessionController.java deleted file mode 100644 index 84624abb9e..0000000000 --- a/core/src/main/java/org/springframework/security/authentication/concurrent/NullConcurrentSessionController.java +++ /dev/null @@ -1,35 +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.concurrent; - -import org.springframework.security.core.Authentication; -import org.springframework.security.core.AuthenticationException; - - -/** - * No-op implementation of {@link org.springframework.security.authentication.concurrent.ConcurrentSessionController}. - * - * @author Ben Alex - * @version $Id$ - */ -class NullConcurrentSessionController implements ConcurrentSessionController { - //~ Methods ======================================================================================================== - - public void checkAuthenticationAllowed(Authentication request) - throws AuthenticationException {} - - public void registerSuccessfulAuthentication(Authentication authentication) {} -} diff --git a/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureConcurrentLoginEvent.java b/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureConcurrentLoginEvent.java deleted file mode 100644 index 48c6c65444..0000000000 --- a/core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureConcurrentLoginEvent.java +++ /dev/null @@ -1,35 +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.event; - -import org.springframework.security.core.Authentication; -import org.springframework.security.core.AuthenticationException; - - -/** - * Application event which indicates authentication failure due to the user attempting to login to too many - * concurrent sessions. - * - * @author Ben Alex - * @version $Id$ - */ -public class AuthenticationFailureConcurrentLoginEvent extends AbstractAuthenticationFailureEvent { - //~ Constructors =================================================================================================== - - public AuthenticationFailureConcurrentLoginEvent(Authentication authentication, AuthenticationException exception) { - super(authentication, exception); - } -} diff --git a/core/src/test/java/org/springframework/security/authentication/ProviderManagerTests.java b/core/src/test/java/org/springframework/security/authentication/ProviderManagerTests.java index 81acc9a7f0..f9276914ad 100644 --- a/core/src/test/java/org/springframework/security/authentication/ProviderManagerTests.java +++ b/core/src/test/java/org/springframework/security/authentication/ProviderManagerTests.java @@ -16,6 +16,7 @@ package org.springframework.security.authentication; import static org.junit.Assert.*; +import static org.mockito.Matchers.any; import static org.mockito.Mockito.*; import java.util.ArrayList; @@ -24,13 +25,6 @@ import java.util.List; import org.junit.Test; import org.springframework.context.MessageSource; -import org.springframework.security.authentication.AuthenticationProvider; -import org.springframework.security.authentication.ProviderManager; -import org.springframework.security.authentication.ProviderNotFoundException; -import org.springframework.security.authentication.TestingAuthenticationToken; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.authentication.concurrent.ConcurrentLoginException; -import org.springframework.security.authentication.concurrent.ConcurrentSessionController; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.GrantedAuthority; @@ -81,18 +75,6 @@ public class ProviderManagerTests { verify(publisher).publishAuthenticationSuccess(result); } - @Test - public void concurrentSessionControllerConfiguration() throws Exception { - ProviderManager target = new ProviderManager(); - - //The NullConcurrentSessionController should be the default - assertNotNull(target.getSessionController()); - - ConcurrentSessionController csc = mock(ConcurrentSessionController.class); - target.setSessionController(csc); - assertSame(csc, target.getSessionController()); - } - @Test(expected=IllegalArgumentException.class) public void startupFailsIfProviderListDoesNotContainProviders() throws Exception { List providers = new ArrayList(); @@ -193,18 +175,6 @@ public class ProviderManagerTests { verifyZeroInteractions(otherProvider); } - @Test(expected=ConcurrentLoginException.class) - public void concurrentLoginExceptionPreventsCallsToSubsequentProviders() throws Exception { - ProviderManager authMgr = makeProviderManager(); - // Two providers so if the second is polled it will throw an BadCredentialsException - authMgr.setProviders(Arrays.asList(new MockProvider(), createProviderWhichThrows(new BadCredentialsException(""))) ); - TestingAuthenticationToken request = createAuthenticationToken(); - ConcurrentSessionController ctrlr = mock(ConcurrentSessionController.class); - doThrow(new ConcurrentLoginException("mocked")).when(ctrlr).checkAuthenticationAllowed(request); - authMgr.setSessionController(ctrlr); - - authMgr.authenticate(request); - } @Test public void parentAuthenticationIsUsedIfProvidersDontAuthenticate() throws Exception { diff --git a/core/src/test/java/org/springframework/security/authentication/concurrent/ConcurrentSessionControllerImplTests.java b/core/src/test/java/org/springframework/security/authentication/concurrent/ConcurrentSessionControllerImplTests.java deleted file mode 100644 index 51560b5acb..0000000000 --- a/core/src/test/java/org/springframework/security/authentication/concurrent/ConcurrentSessionControllerImplTests.java +++ /dev/null @@ -1,112 +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.concurrent; - -import static org.junit.Assert.*; - -import org.junit.Test; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.authentication.concurrent.ConcurrentLoginException; -import org.springframework.security.authentication.concurrent.ConcurrentSessionControllerImpl; -import org.springframework.security.authentication.concurrent.SessionIdentifierAware; -import org.springframework.security.authentication.concurrent.SessionRegistry; -import org.springframework.security.authentication.concurrent.SessionRegistryImpl; -import org.springframework.security.core.Authentication; - - -/** - * Tests {@link ConcurrentSessionControllerImpl}. - * - * @author Ben Alex - * @version $Id$ - */ -public class ConcurrentSessionControllerImplTests { - //~ Methods ======================================================================================================== - - private static int nextSessionId = 1000; - - private Authentication createAuthentication(String user, String password) { - UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(user, password); - auth.setDetails(new SessionIdentifierAware() { - private final String id = Integer.toString(nextSessionId++); - public String getSessionId() { - return id; - } - }); - - return auth; - } - - @Test - public void testLifecycle() throws Exception { - // Build a test fixture - ConcurrentSessionControllerImpl sc = new ConcurrentSessionControllerImpl(); - SessionRegistry registry = new SessionRegistryImpl(); - sc.setSessionRegistry(registry); - - // Attempt to authenticate - it should be successful - Authentication auth = createAuthentication("bob", "1212"); - sc.checkAuthenticationAllowed(auth); - sc.registerSuccessfulAuthentication(auth); - - String sessionId1 = ((SessionIdentifierAware) auth.getDetails()).getSessionId(); - assertFalse(registry.getSessionInformation(sessionId1).isExpired()); - - // Attempt to authenticate again - it should still be successful - sc.checkAuthenticationAllowed(auth); - sc.registerSuccessfulAuthentication(auth); - - // Attempt to authenticate with a different session for same principal - should fail - sc.setExceptionIfMaximumExceeded(true); - - Authentication auth2 = createAuthentication("bob", "1212"); - assertFalse(registry.getSessionInformation(sessionId1).isExpired()); - - try { - sc.checkAuthenticationAllowed(auth2); - fail("Should have thrown ConcurrentLoginException"); - } catch (ConcurrentLoginException expected) { - assertTrue(true); - } - - // Attempt to authenticate with a different session for same principal - should expire first session - sc.setExceptionIfMaximumExceeded(false); - - Authentication auth3 = createAuthentication("bob", "1212"); - sc.checkAuthenticationAllowed(auth3); - sc.registerSuccessfulAuthentication(auth3); - - String sessionId3 = ((SessionIdentifierAware) auth3.getDetails()).getSessionId(); - assertTrue(registry.getSessionInformation(sessionId1).isExpired()); - assertFalse(registry.getSessionInformation(sessionId3).isExpired()); - } - - @Test(expected=IllegalArgumentException.class) - public void startupDetectsInvalidMaximumSessions() throws Exception { - ConcurrentSessionControllerImpl sc = new ConcurrentSessionControllerImpl(); - sc.setMaximumSessions(0); - - sc.afterPropertiesSet(); - } - - @Test(expected=IllegalArgumentException.class) - public void startupDetectsInvalidSessionRegistry() throws Exception { - ConcurrentSessionControllerImpl sc = new ConcurrentSessionControllerImpl(); - sc.setSessionRegistry(null); - - sc.afterPropertiesSet(); - } -}