diff --git a/config/src/main/java/org/springframework/security/config/http/HttpConfigurationBuilder.java b/config/src/main/java/org/springframework/security/config/http/HttpConfigurationBuilder.java
index 9a387709e2..bcbae721fc 100644
--- a/config/src/main/java/org/springframework/security/config/http/HttpConfigurationBuilder.java
+++ b/config/src/main/java/org/springframework/security/config/http/HttpConfigurationBuilder.java
@@ -24,8 +24,8 @@ import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.security.access.vote.AffirmativeBased;
import org.springframework.security.access.vote.AuthenticatedVoter;
import org.springframework.security.access.vote.RoleVoter;
-import org.springframework.security.authentication.concurrent.SessionRegistryImpl;
import org.springframework.security.config.Elements;
+import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator;
import org.springframework.security.web.access.channel.ChannelDecisionManagerImpl;
import org.springframework.security.web.access.channel.ChannelProcessingFilter;
@@ -42,7 +42,7 @@ import org.springframework.security.web.authentication.concurrent.ConcurrentSess
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.security.web.context.SecurityContextPersistenceFilter;
import org.springframework.security.web.session.ConcurrentSessionControlStrategy;
-import org.springframework.security.web.session.DefaultSessionAuthenticationStrategy;
+import org.springframework.security.web.session.SessionFixationProtectionStrategy;
import org.springframework.security.web.session.SessionManagementFilter;
import org.springframework.security.web.util.AntUrlPathMatcher;
import org.springframework.security.web.util.UrlMatcher;
@@ -248,7 +248,7 @@ class HttpConfigurationBuilder {
}
} else if (sessionFixationProtectionRequired || StringUtils.hasText(invalidSessionUrl)
|| StringUtils.hasText(sessionAuthStratRef)) {
- sessionStrategy = BeanDefinitionBuilder.rootBeanDefinition(DefaultSessionAuthenticationStrategy.class);
+ sessionStrategy = BeanDefinitionBuilder.rootBeanDefinition(SessionFixationProtectionStrategy.class);
} else {
sfpf = null;
return;
diff --git a/config/src/test/java/org/springframework/security/config/http/HttpSecurityBeanDefinitionParserTests.java b/config/src/test/java/org/springframework/security/config/http/HttpSecurityBeanDefinitionParserTests.java
index b22dac8ea7..9a20812445 100644
--- a/config/src/test/java/org/springframework/security/config/http/HttpSecurityBeanDefinitionParserTests.java
+++ b/config/src/test/java/org/springframework/security/config/http/HttpSecurityBeanDefinitionParserTests.java
@@ -27,11 +27,11 @@ import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
-import org.springframework.security.authentication.concurrent.SessionRegistryImpl;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.PostProcessedMockUserDetailsService;
import org.springframework.security.config.util.InMemoryXmlApplicationContext;
import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.openid.OpenID4JavaConsumer;
import org.springframework.security.openid.OpenIDAttribute;
import org.springframework.security.openid.OpenIDAuthenticationProcessingFilter;
diff --git a/core/src/main/java/org/springframework/security/authentication/concurrent/ConcurrentSessionController.java b/core/src/main/java/org/springframework/security/authentication/concurrent/ConcurrentSessionController.java
deleted file mode 100644
index c09e570d51..0000000000
--- a/core/src/main/java/org/springframework/security/authentication/concurrent/ConcurrentSessionController.java
+++ /dev/null
@@ -1,55 +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;
-
-
-/**
- * Provides two methods that can be called by an {@link
- * org.springframework.security.authentication.AuthenticationManager} to integrate with the
- * concurrent session handling infrastructure.
- *
- * @author Ben Alex
- * @version $Id$
- */
-public interface ConcurrentSessionController {
- //~ Methods ========================================================================================================
-
- /**
- * Called by any class that wishes to know whether the current authentication request should be permitted.
- * Generally callers will be AuthenticationManagers before they authenticate, but could equally
- * include Filters or other interceptors that wish to confirm the ongoing validity of a previously
- * authenticated Authentication.
The implementation should throw a suitable exception if the - * user has exceeded their maximum allowed concurrent sessions.
- * - * @param request the authentication request (nevernull)
- *
- * @throws AuthenticationException if the user has exceeded their maximum allowed current sessions
- */
- void checkAuthenticationAllowed(Authentication request)
- throws AuthenticationException;
-
- /**
- * Called by an AuthenticationManager when the authentication was successful. An
- * implementation is expected to register the authenticated user in some sort of registry, for future concurrent
- * tracking via the {@link #checkAuthenticationAllowed(Authentication)} method.
- *
- * @param authentication the successfully authenticated user (never null)
- */
- void registerSuccessfulAuthentication(Authentication authentication);
-}
diff --git a/core/src/main/java/org/springframework/security/authentication/concurrent/package.html b/core/src/main/java/org/springframework/security/authentication/concurrent/package.html
deleted file mode 100644
index 9235ec5043..0000000000
--- a/core/src/main/java/org/springframework/security/authentication/concurrent/package.html
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-Concurrent session control and registration classes.
-
-
-
diff --git a/core/src/main/java/org/springframework/security/authentication/concurrent/SessionIdentifierAware.java b/core/src/main/java/org/springframework/security/core/session/SessionIdentifierAware.java
similarity index 96%
rename from core/src/main/java/org/springframework/security/authentication/concurrent/SessionIdentifierAware.java
rename to core/src/main/java/org/springframework/security/core/session/SessionIdentifierAware.java
index a84a4468d2..417205c7a8 100644
--- a/core/src/main/java/org/springframework/security/authentication/concurrent/SessionIdentifierAware.java
+++ b/core/src/main/java/org/springframework/security/core/session/SessionIdentifierAware.java
@@ -13,7 +13,7 @@
* limitations under the License.
*/
-package org.springframework.security.authentication.concurrent;
+package org.springframework.security.core.session;
/**
* Implemented by {@link org.springframework.security.core.Authentication#getDetails()}
diff --git a/core/src/main/java/org/springframework/security/authentication/concurrent/SessionInformation.java b/core/src/main/java/org/springframework/security/core/session/SessionInformation.java
similarity index 97%
rename from core/src/main/java/org/springframework/security/authentication/concurrent/SessionInformation.java
rename to core/src/main/java/org/springframework/security/core/session/SessionInformation.java
index 0217bf35d4..de1db8bab7 100644
--- a/core/src/main/java/org/springframework/security/authentication/concurrent/SessionInformation.java
+++ b/core/src/main/java/org/springframework/security/core/session/SessionInformation.java
@@ -13,7 +13,7 @@
* limitations under the License.
*/
-package org.springframework.security.authentication.concurrent;
+package org.springframework.security.core.session;
import org.springframework.util.Assert;
diff --git a/core/src/main/java/org/springframework/security/authentication/concurrent/SessionRegistry.java b/core/src/main/java/org/springframework/security/core/session/SessionRegistry.java
similarity index 98%
rename from core/src/main/java/org/springframework/security/authentication/concurrent/SessionRegistry.java
rename to core/src/main/java/org/springframework/security/core/session/SessionRegistry.java
index be3bb470a0..9496b923a4 100644
--- a/core/src/main/java/org/springframework/security/authentication/concurrent/SessionRegistry.java
+++ b/core/src/main/java/org/springframework/security/core/session/SessionRegistry.java
@@ -13,7 +13,7 @@
* limitations under the License.
*/
-package org.springframework.security.authentication.concurrent;
+package org.springframework.security.core.session;
import java.util.List;
diff --git a/core/src/main/java/org/springframework/security/authentication/concurrent/SessionRegistryImpl.java b/core/src/main/java/org/springframework/security/core/session/SessionRegistryImpl.java
similarity index 96%
rename from core/src/main/java/org/springframework/security/authentication/concurrent/SessionRegistryImpl.java
rename to core/src/main/java/org/springframework/security/core/session/SessionRegistryImpl.java
index e988793c96..c044ee52f9 100644
--- a/core/src/main/java/org/springframework/security/authentication/concurrent/SessionRegistryImpl.java
+++ b/core/src/main/java/org/springframework/security/core/session/SessionRegistryImpl.java
@@ -13,7 +13,7 @@
* limitations under the License.
*/
-package org.springframework.security.authentication.concurrent;
+package org.springframework.security.core.session;
import java.util.ArrayList;
import java.util.Arrays;
@@ -28,11 +28,10 @@ import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationListener;
-import org.springframework.security.core.session.SessionDestroyedEvent;
import org.springframework.util.Assert;
/**
- * Base implementation of {@link org.springframework.security.authentication.concurrent.SessionRegistry}
+ * Base implementation of {@link org.springframework.security.core.session.SessionRegistry}
* which also listens for {@link org.springframework.security.web.session.HttpSessionDestroyedEvent}s
* published in the Spring application context.
*
diff --git a/core/src/main/java/org/springframework/security/core/session/package.html b/core/src/main/java/org/springframework/security/core/session/package.html
new file mode 100644
index 0000000000..690d318501
--- /dev/null
+++ b/core/src/main/java/org/springframework/security/core/session/package.html
@@ -0,0 +1,6 @@
+
+
+Session registry and other related classes.
+
+
+
diff --git a/core/src/test/java/org/springframework/security/authentication/concurrent/SessionInformationTests.java b/core/src/test/java/org/springframework/security/core/session/SessionInformationTests.java
similarity index 91%
rename from core/src/test/java/org/springframework/security/authentication/concurrent/SessionInformationTests.java
rename to core/src/test/java/org/springframework/security/core/session/SessionInformationTests.java
index ecaffc5f62..d053423e5d 100644
--- a/core/src/test/java/org/springframework/security/authentication/concurrent/SessionInformationTests.java
+++ b/core/src/test/java/org/springframework/security/core/session/SessionInformationTests.java
@@ -13,13 +13,13 @@
* limitations under the License.
*/
-package org.springframework.security.authentication.concurrent;
+package org.springframework.security.core.session;
import junit.framework.TestCase;
import java.util.Date;
-import org.springframework.security.authentication.concurrent.SessionInformation;
+import org.springframework.security.core.session.SessionInformation;
/**
diff --git a/core/src/test/java/org/springframework/security/authentication/concurrent/SessionRegistryImplTests.java b/core/src/test/java/org/springframework/security/core/session/SessionRegistryImplTests.java
similarity index 97%
rename from core/src/test/java/org/springframework/security/authentication/concurrent/SessionRegistryImplTests.java
rename to core/src/test/java/org/springframework/security/core/session/SessionRegistryImplTests.java
index fc8e3632bc..6b2fcbecc3 100644
--- a/core/src/test/java/org/springframework/security/authentication/concurrent/SessionRegistryImplTests.java
+++ b/core/src/test/java/org/springframework/security/core/session/SessionRegistryImplTests.java
@@ -13,7 +13,7 @@
* limitations under the License.
*/
-package org.springframework.security.authentication.concurrent;
+package org.springframework.security.core.session;
import static org.junit.Assert.*;
@@ -24,6 +24,8 @@ import org.junit.Before;
import org.junit.Test;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.session.SessionDestroyedEvent;
+import org.springframework.security.core.session.SessionInformation;
+import org.springframework.security.core.session.SessionRegistryImpl;
/**
* Tests {@link SessionRegistryImpl}.
diff --git a/docs/manual/src/docbook/appendix-namespace.xml b/docs/manual/src/docbook/appendix-namespace.xml
index 26733a136f..2e34f199ff 100644
--- a/docs/manual/src/docbook/appendix-namespace.xml
+++ b/docs/manual/src/docbook/appendix-namespace.xml
@@ -298,18 +298,17 @@
* This filter performs two functions. First, it calls
- * {@link org.springframework.security.authentication.concurrent.SessionRegistry#refreshLastRequest(String)} for each request
+ * {@link org.springframework.security.core.session.SessionRegistry#refreshLastRequest(String)} for each request
* so that registered sessions always have a correct "last update" date/time. Second, it retrieves a
- * {@link org.springframework.security.authentication.concurrent.SessionInformation} from the SessionRegistry
+ * {@link org.springframework.security.core.session.SessionInformation} from the SessionRegistry
* for each request and checks if the session has been marked as expired.
* If it has been marked as expired, the configured logout handlers will be called (as happens with
* {@link org.springframework.security.web.authentication.logout.LogoutFilter}), typically to invalidate the session.
diff --git a/web/src/main/java/org/springframework/security/web/session/ConcurrentSessionControlStrategy.java b/web/src/main/java/org/springframework/security/web/session/ConcurrentSessionControlStrategy.java
index 35ef91cefe..c42baa0c3d 100644
--- a/web/src/main/java/org/springframework/security/web/session/ConcurrentSessionControlStrategy.java
+++ b/web/src/main/java/org/springframework/security/web/session/ConcurrentSessionControlStrategy.java
@@ -9,20 +9,36 @@ import javax.servlet.http.HttpSession;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.support.MessageSourceAccessor;
-import org.springframework.security.authentication.concurrent.SessionInformation;
-import org.springframework.security.authentication.concurrent.SessionRegistry;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.SpringSecurityMessageSource;
+import org.springframework.security.core.session.SessionInformation;
+import org.springframework.security.core.session.SessionRegistry;
+import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationProcessingFilter;
+import org.springframework.security.web.authentication.concurrent.ConcurrentSessionFilter;
import org.springframework.util.Assert;
/**
+ * Strategy which handles concurrent session-control, in addition to the functionality provided by the base class.
+ *
+ * When invoked following an authentication, it will check whether the user in question should be allowed to proceed,
+ * by comparing the number of sessions they already have active with the configured maximumSessions value.
+ * The {@link SessionRegistry} is used as the source of data on authenticated users and session data.
+ *
+ * If a user has reached the maximum number of permitted sessions, the behaviour depends on the + * exceptionIfMaxExceeded property. The default behaviour is to expired the least recently used session, which + * will be invalidated by the {@link ConcurrentSessionFilter} if accessed again. If exceptionIfMaxExceeded is + * set to true, however, the user will be prevented from starting a new authenticated session. + *
+ * This strategy can be injected into both the {@link SessionManagementFilter} and instances of
+ * {@link AbstractAuthenticationProcessingFilter} (typically {@link UsernamePasswordAuthenticationProcessingFilter}).
*
* @author Luke Taylor
* @version $Id$
* @since 3.0
*/
-public class ConcurrentSessionControlStrategy extends DefaultSessionAuthenticationStrategy
+public class ConcurrentSessionControlStrategy extends SessionFixationProtectionStrategy
implements MessageSourceAware {
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
private final SessionRegistry sessionRegistry;
@@ -106,7 +122,7 @@ public class ConcurrentSessionControlStrategy extends DefaultSessionAuthenticati
*
*/
protected void allowableSessionsExceeded(List