Sfoglia il codice sorgente

SEC-1229: Removed legacy concurrency classes

Luke Taylor 16 anni fa
parent
commit
2a1430f1ce

+ 2 - 26
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 =
-        "<b:bean id='sc' class='" + ConcurrentSessionControllerImpl.class.getName() + "'>" +
-        "  <b:property name='sessionRegistry'>" +
-        "      <b:bean class='" + SessionRegistryImpl.class.getName() + "'/>" +
-        "  </b:property>" +
-        "</b:bean>";
-
     @Test
     // SEC-1225
     public void providersAreRegisteredAsTopLevelBeans() throws Exception {
@@ -36,23 +25,10 @@ public class AuthenticationManagerBeanDefinitionParserTests {
           "            <user name='bob' password='bobspassword' authorities='ROLE_A,ROLE_B' />" +
           "        </user-service>" +
           "    </authentication-provider>" +
-          "</authentication-manager>" + SESSION_CONTROLLER, "3.0");
+          "</authentication-manager>", "3.0");
         assertEquals(1, appContext.getBeansOfType(AuthenticationProvider.class).size());
     }
 
-    @Test(expected=XmlBeanDefinitionStoreException.class)
-    public void sessionControllerRefAttributeIsRejectedFor30Context() throws Exception {
-        setContext(
-          "<authentication-manager session-controller-ref='sc'>" +
-          "    <authentication-provider>" +
-          "        <user-service>" +
-          "            <user name='bob' password='bobspassword' authorities='ROLE_A,ROLE_B' />" +
-          "        </user-service>" +
-          "    </authentication-provider>" +
-          "</authentication-manager>" + SESSION_CONTROLLER, "3.0");
-        appContext.getBean(BeanIds.AUTHENTICATION_MANAGER);
-    }
-
     private void setContext(String context, String version) {
         appContext = new InMemoryXmlApplicationContext(context, version, null);
     }

+ 0 - 4
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",

+ 7 - 45
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.
  * <p>
  * <tt>AuthenticationProvider</tt>s 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 <code>Authentication</code>,
  * the <code>ProviderManager</code> will throw a <code>ProviderNotFoundException</code>.
  * <p>
- * 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.
  *
  * <h2>Event Publishing</h2>
  * <p>
@@ -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<AuthenticationProvider> 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) {}
-    }
 }

+ 0 - 34
core/src/main/java/org/springframework/security/authentication/concurrent/ConcurrentLoginException.java

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

+ 0 - 174
core/src/main/java/org/springframework/security/authentication/concurrent/ConcurrentSessionControllerImpl.java

@@ -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<SessionInformation> 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 <code>null</code> 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 <code>SessionRegistry</code> for subclass use
-     *
-     * @throws ConcurrentLoginException if the
-     */
-    protected void allowableSessionsExceeded(String sessionId, List<SessionInformation> 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 <code>maximumSessions</code> 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;
-    }
-}

+ 0 - 35
core/src/main/java/org/springframework/security/authentication/concurrent/NullConcurrentSessionController.java

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

+ 0 - 35
core/src/main/java/org/springframework/security/authentication/event/AuthenticationFailureConcurrentLoginEvent.java

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

+ 1 - 31
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<Object> providers = new ArrayList<Object>();
@@ -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 {

+ 0 - 112
core/src/test/java/org/springframework/security/authentication/concurrent/ConcurrentSessionControllerImplTests.java

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