diff --git a/config/src/main/java/org/springframework/security/config/ConcurrentSessionsBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/ConcurrentSessionsBeanDefinitionParser.java
index 8696a0dab4..5333c1fc21 100644
--- a/config/src/main/java/org/springframework/security/config/ConcurrentSessionsBeanDefinitionParser.java
+++ b/config/src/main/java/org/springframework/security/config/ConcurrentSessionsBeanDefinitionParser.java
@@ -11,8 +11,8 @@ import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.concurrent.ConcurrentSessionControllerImpl;
+import org.springframework.security.authentication.concurrent.SessionRegistryImpl;
import org.springframework.security.web.concurrent.ConcurrentSessionFilter;
-import org.springframework.security.web.concurrent.SessionRegistryImpl;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
diff --git a/config/src/test/java/org/springframework/security/config/HttpSecurityBeanDefinitionParserTests.java b/config/src/test/java/org/springframework/security/config/HttpSecurityBeanDefinitionParserTests.java
index d2434ac101..749a2de8e0 100644
--- a/config/src/test/java/org/springframework/security/config/HttpSecurityBeanDefinitionParserTests.java
+++ b/config/src/test/java/org/springframework/security/config/HttpSecurityBeanDefinitionParserTests.java
@@ -27,6 +27,7 @@ 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.ConcurrentSessionControllerImpl;
+import org.springframework.security.authentication.concurrent.SessionRegistryImpl;
import org.springframework.security.config.util.InMemoryXmlApplicationContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.openid.OpenIDAuthenticationProcessingFilter;
@@ -51,7 +52,6 @@ import org.springframework.security.web.authentication.rememberme.PersistentToke
import org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices;
import org.springframework.security.web.authentication.www.BasicProcessingFilter;
import org.springframework.security.web.concurrent.ConcurrentSessionFilter;
-import org.springframework.security.web.concurrent.SessionRegistryImpl;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.security.web.context.SecurityContextPersistenceFilter;
import org.springframework.security.web.expression.DefaultWebSecurityExpressionHandler;
diff --git a/config/src/test/java/org/springframework/security/config/SessionRegistryInjectionBeanPostProcessorTests.java b/config/src/test/java/org/springframework/security/config/SessionRegistryInjectionBeanPostProcessorTests.java
index bf1bd83d0a..9ca9df72df 100644
--- a/config/src/test/java/org/springframework/security/config/SessionRegistryInjectionBeanPostProcessorTests.java
+++ b/config/src/test/java/org/springframework/security/config/SessionRegistryInjectionBeanPostProcessorTests.java
@@ -7,11 +7,11 @@ import org.junit.Test;
import org.springframework.context.support.AbstractXmlApplicationContext;
import org.springframework.security.authentication.concurrent.ConcurrentSessionController;
import org.springframework.security.authentication.concurrent.ConcurrentSessionControllerImpl;
+import org.springframework.security.authentication.concurrent.SessionRegistryImpl;
import org.springframework.security.config.util.InMemoryXmlApplicationContext;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.util.FieldUtils;
-import org.springframework.security.web.concurrent.SessionRegistryImpl;
/**
*
diff --git a/core/src/main/java/org/springframework/security/authentication/concurrent/SessionAlreadyUsedException.java b/core/src/main/java/org/springframework/security/authentication/concurrent/SessionAlreadyUsedException.java
deleted file mode 100644
index b4df1c7a41..0000000000
--- a/core/src/main/java/org/springframework/security/authentication/concurrent/SessionAlreadyUsedException.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 a SessionRegistry implementation if an attempt is made to create new session information
- * for an existing sessionId. The user should firstly clear the existing session from the
- * ConcurrentSessionRegistry.
- *
- * @author Ben Alex
- */
-public class SessionAlreadyUsedException extends AuthenticationException {
- //~ Constructors ===================================================================================================
-
- public SessionAlreadyUsedException(String msg) {
- super(msg);
- }
-}
diff --git a/core/src/main/java/org/springframework/security/authentication/concurrent/SessionRegistry.java b/core/src/main/java/org/springframework/security/authentication/concurrent/SessionRegistry.java
index f8a7236515..69b2ba66e3 100644
--- a/core/src/main/java/org/springframework/security/authentication/concurrent/SessionRegistry.java
+++ b/core/src/main/java/org/springframework/security/authentication/concurrent/SessionRegistry.java
@@ -67,11 +67,8 @@ public interface SessionRegistry {
*
* @param sessionId to associate with the principal (should never be null)
* @param principal to associate with the session (should never be null)
- *
- * @throws SessionAlreadyUsedException DOCUMENT ME!
*/
- void registerNewSession(String sessionId, Object principal)
- throws SessionAlreadyUsedException;
+ void registerNewSession(String sessionId, Object principal);
/**
* Deletes all the session information being maintained for the specified sessionId. If the
diff --git a/web/src/main/java/org/springframework/security/web/concurrent/SessionRegistryImpl.java b/core/src/main/java/org/springframework/security/authentication/concurrent/SessionRegistryImpl.java
similarity index 90%
rename from web/src/main/java/org/springframework/security/web/concurrent/SessionRegistryImpl.java
rename to core/src/main/java/org/springframework/security/authentication/concurrent/SessionRegistryImpl.java
index ec61e15f91..be9bdbf75b 100644
--- a/web/src/main/java/org/springframework/security/web/concurrent/SessionRegistryImpl.java
+++ b/core/src/main/java/org/springframework/security/authentication/concurrent/SessionRegistryImpl.java
@@ -13,7 +13,7 @@
* limitations under the License.
*/
-package org.springframework.security.web.concurrent;
+package org.springframework.security.authentication.concurrent;
import java.util.ArrayList;
import java.util.Collections;
@@ -24,15 +24,10 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
-import javax.servlet.http.HttpSession;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
-import org.springframework.security.authentication.concurrent.SessionInformation;
-import org.springframework.security.authentication.concurrent.SessionRegistry;
-import org.springframework.security.web.session.HttpSessionDestroyedEvent;
+import org.springframework.security.core.session.SessionDestroyedEvent;
import org.springframework.util.Assert;
/**
@@ -48,7 +43,7 @@ import org.springframework.util.Assert;
* @author Ben Alex
* @version $Id$
*/
-public class SessionRegistryImpl implements SessionRegistry, ApplicationListener {
+public class SessionRegistryImpl implements SessionRegistry, ApplicationListener {
//~ Static fields/initializers =====================================================================================
protected static final Log logger = LogFactory.getLog(SessionRegistryImpl.class);
@@ -98,11 +93,9 @@ public class SessionRegistryImpl implements SessionRegistry, ApplicationListener
return (SessionInformation) sessionIds.get(sessionId);
}
- public void onApplicationEvent(ApplicationEvent event) {
- if (event instanceof HttpSessionDestroyedEvent) {
- String sessionId = ((HttpSession) event.getSource()).getId();
- removeSessionInformation(sessionId);
- }
+ public void onApplicationEvent(SessionDestroyedEvent event) {
+ String sessionId = event.getId();
+ removeSessionInformation(sessionId);
}
public void refreshLastRequest(String sessionId) {
diff --git a/core/src/main/java/org/springframework/security/core/session/SessionDestroyedEvent.java b/core/src/main/java/org/springframework/security/core/session/SessionDestroyedEvent.java
index b7f23064b7..c66b8f938c 100644
--- a/core/src/main/java/org/springframework/security/core/session/SessionDestroyedEvent.java
+++ b/core/src/main/java/org/springframework/security/core/session/SessionDestroyedEvent.java
@@ -23,4 +23,10 @@ public abstract class SessionDestroyedEvent extends ApplicationEvent {
* @return the SecurityContext associated with the session, or null if there is no context.
*/
public abstract SecurityContext getSecurityContext();
+
+ /**
+ * The identifier associated with the destroyed session.
+ * @return
+ */
+ public abstract String getId();
}
diff --git a/web/src/test/java/org/springframework/security/web/concurrent/ConcurrentSessionControllerImplTests.java b/core/src/test/java/org/springframework/security/authentication/concurrent/ConcurrentSessionControllerImplTests.java
similarity index 69%
rename from web/src/test/java/org/springframework/security/web/concurrent/ConcurrentSessionControllerImplTests.java
rename to core/src/test/java/org/springframework/security/authentication/concurrent/ConcurrentSessionControllerImplTests.java
index 4a112601c4..51560b5acb 100644
--- a/web/src/test/java/org/springframework/security/web/concurrent/ConcurrentSessionControllerImplTests.java
+++ b/core/src/test/java/org/springframework/security/authentication/concurrent/ConcurrentSessionControllerImplTests.java
@@ -13,23 +13,19 @@
* limitations under the License.
*/
-package org.springframework.security.web.concurrent;
-
-import junit.framework.TestCase;
+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;
-import org.springframework.security.web.authentication.WebAuthenticationDetails;
-import org.springframework.security.web.concurrent.SessionRegistryImpl;
-
-import org.springframework.mock.web.MockHttpServletRequest;
-import org.springframework.mock.web.MockHttpSession;
-
/**
* Tests {@link ConcurrentSessionControllerImpl}.
@@ -37,25 +33,24 @@ import org.springframework.mock.web.MockHttpSession;
* @author Ben Alex
* @version $Id$
*/
-public class ConcurrentSessionControllerImplTests extends TestCase {
+public class ConcurrentSessionControllerImplTests {
//~ Methods ========================================================================================================
+ private static int nextSessionId = 1000;
+
private Authentication createAuthentication(String user, String password) {
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(user, password);
- auth.setDetails(createWebDetails(auth));
+ auth.setDetails(new SessionIdentifierAware() {
+ private final String id = Integer.toString(nextSessionId++);
+ public String getSessionId() {
+ return id;
+ }
+ });
return auth;
}
- private WebAuthenticationDetails createWebDetails(Authentication auth) {
- MockHttpSession session = new MockHttpSession();
- MockHttpServletRequest request = new MockHttpServletRequest();
- request.setSession(session);
- request.setUserPrincipal(auth);
-
- return new WebAuthenticationDetails(request);
- }
-
+ @Test
public void testLifecycle() throws Exception {
// Build a test fixture
ConcurrentSessionControllerImpl sc = new ConcurrentSessionControllerImpl();
@@ -67,7 +62,7 @@ public class ConcurrentSessionControllerImplTests extends TestCase {
sc.checkAuthenticationAllowed(auth);
sc.registerSuccessfulAuthentication(auth);
- String sessionId1 = ((WebAuthenticationDetails) auth.getDetails()).getSessionId();
+ String sessionId1 = ((SessionIdentifierAware) auth.getDetails()).getSessionId();
assertFalse(registry.getSessionInformation(sessionId1).isExpired());
// Attempt to authenticate again - it should still be successful
@@ -94,34 +89,24 @@ public class ConcurrentSessionControllerImplTests extends TestCase {
sc.checkAuthenticationAllowed(auth3);
sc.registerSuccessfulAuthentication(auth3);
- String sessionId3 = ((WebAuthenticationDetails) auth3.getDetails()).getSessionId();
+ String sessionId3 = ((SessionIdentifierAware) auth3.getDetails()).getSessionId();
assertTrue(registry.getSessionInformation(sessionId1).isExpired());
assertFalse(registry.getSessionInformation(sessionId3).isExpired());
}
- public void testStartupDetectsInvalidMaximumSessions()
- throws Exception {
+ @Test(expected=IllegalArgumentException.class)
+ public void startupDetectsInvalidMaximumSessions() throws Exception {
ConcurrentSessionControllerImpl sc = new ConcurrentSessionControllerImpl();
sc.setMaximumSessions(0);
- try {
- sc.afterPropertiesSet();
- fail("Should have thrown IAE");
- } catch (IllegalArgumentException expected) {
- assertTrue(true);
- }
+ sc.afterPropertiesSet();
}
- public void testStartupDetectsInvalidSessionRegistry()
- throws Exception {
+ @Test(expected=IllegalArgumentException.class)
+ public void startupDetectsInvalidSessionRegistry() throws Exception {
ConcurrentSessionControllerImpl sc = new ConcurrentSessionControllerImpl();
sc.setSessionRegistry(null);
- try {
- sc.afterPropertiesSet();
- fail("Should have thrown IAE");
- } catch (IllegalArgumentException expected) {
- assertTrue(true);
- }
+ sc.afterPropertiesSet();
}
}
diff --git a/web/src/test/java/org/springframework/security/web/concurrent/SessionInformationTests.java b/core/src/test/java/org/springframework/security/authentication/concurrent/SessionInformationTests.java
similarity index 96%
rename from web/src/test/java/org/springframework/security/web/concurrent/SessionInformationTests.java
rename to core/src/test/java/org/springframework/security/authentication/concurrent/SessionInformationTests.java
index 3d33c2cda8..bd04fbefb1 100644
--- a/web/src/test/java/org/springframework/security/web/concurrent/SessionInformationTests.java
+++ b/core/src/test/java/org/springframework/security/authentication/concurrent/SessionInformationTests.java
@@ -13,7 +13,7 @@
* limitations under the License.
*/
-package org.springframework.security.web.concurrent;
+package org.springframework.security.authentication.concurrent;
import junit.framework.TestCase;
diff --git a/web/src/test/java/org/springframework/security/web/concurrent/SessionRegistryImplTests.java b/core/src/test/java/org/springframework/security/authentication/concurrent/SessionRegistryImplTests.java
similarity index 85%
rename from web/src/test/java/org/springframework/security/web/concurrent/SessionRegistryImplTests.java
rename to core/src/test/java/org/springframework/security/authentication/concurrent/SessionRegistryImplTests.java
index f7df160183..c481887f8d 100644
--- a/web/src/test/java/org/springframework/security/web/concurrent/SessionRegistryImplTests.java
+++ b/core/src/test/java/org/springframework/security/authentication/concurrent/SessionRegistryImplTests.java
@@ -13,49 +13,59 @@
* limitations under the License.
*/
-package org.springframework.security.web.concurrent;
+package org.springframework.security.authentication.concurrent;
-import junit.framework.TestCase;
-
-import org.springframework.security.authentication.concurrent.SessionInformation;
-import org.springframework.security.web.concurrent.SessionRegistryImpl;
-import org.springframework.security.web.session.HttpSessionDestroyedEvent;
-
-import org.springframework.mock.web.MockHttpSession;
+import static org.junit.Assert.*;
import java.util.Date;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.session.SessionDestroyedEvent;
+
/**
* Tests {@link SessionRegistryImpl}.
*
-* @author Ben Alex
+ * @author Ben Alex
* @version $Id$
*/
-public class SessionRegistryImplTests extends TestCase {
+public class SessionRegistryImplTests {
private SessionRegistryImpl sessionRegistry;
//~ Methods ========================================================================================================
- protected void setUp() throws Exception {
+ @Before
+ public void setUp() throws Exception {
sessionRegistry = new SessionRegistryImpl();
}
- public void testEventPublishing() {
- MockHttpSession httpSession = new MockHttpSession();
+ @Test
+ public void sessionDestroyedEventRemovesSessionFromRegistry() {
Object principal = "Some principal object";
- String sessionId = httpSession.getId();
- assertNotNull(sessionId);
+ final String sessionId = "zzzz";
// Register new Session
sessionRegistry.registerNewSession(sessionId, principal);
- // Deregister session via an ApplicationEvent
- sessionRegistry.onApplicationEvent(new HttpSessionDestroyedEvent(httpSession));
+ // De-register session via an ApplicationEvent
+ sessionRegistry.onApplicationEvent(new SessionDestroyedEvent("") {
+ @Override
+ public String getId() {
+ return sessionId;
+ }
+
+ @Override
+ public SecurityContext getSecurityContext() {
+ return null;
+ }
+ });
// Check attempts to retrieve cleared session return null
assertNull(sessionRegistry.getSessionInformation(sessionId));
}
+ @Test
public void testMultiplePrincipals() throws Exception {
Object principal1 = "principal_1";
Object principal2 = "principal_2";
@@ -71,6 +81,7 @@ public class SessionRegistryImplTests extends TestCase {
assertEquals(principal2, sessionRegistry.getAllPrincipals()[1]);
}
+ @Test
public void testSessionInformationLifecycle() throws Exception {
Object principal = "Some principal object";
String sessionId = "1234567890";
@@ -106,6 +117,7 @@ public class SessionRegistryImplTests extends TestCase {
assertNull(sessionRegistry.getAllSessions(principal, false));
}
+ @Test
public void testTwoSessionsOnePrincipalExpiring() throws Exception {
Object principal = "Some principal object";
String sessionId1 = "1234567890";
@@ -130,6 +142,7 @@ public class SessionRegistryImplTests extends TestCase {
assertFalse(sessionRegistry.getSessionInformation(sessionId1).isExpired());
}
+ @Test
public void testTwoSessionsOnePrincipalHandling() throws Exception {
Object principal = "Some principal object";
String sessionId1 = "1234567890";
@@ -155,7 +168,7 @@ public class SessionRegistryImplTests extends TestCase {
assertNull(sessionRegistry.getAllSessions(principal, false));
}
- boolean contains(String sessionId, Object principal) {
+ private boolean contains(String sessionId, Object principal) {
SessionInformation[] info = sessionRegistry.getAllSessions(principal, false);
for (int i = 0; i < info.length; i++) {
diff --git a/web/src/main/java/org/springframework/security/web/session/HttpSessionDestroyedEvent.java b/web/src/main/java/org/springframework/security/web/session/HttpSessionDestroyedEvent.java
index cd0a8b1e0c..cb7f219e51 100644
--- a/web/src/main/java/org/springframework/security/web/session/HttpSessionDestroyedEvent.java
+++ b/web/src/main/java/org/springframework/security/web/session/HttpSessionDestroyedEvent.java
@@ -35,11 +35,17 @@ public class HttpSessionDestroyedEvent extends SessionDestroyedEvent {
super(session);
}
+ public HttpSession getSession() {
+ return (HttpSession) getSource();
+ }
+
+ @Override
public SecurityContext getSecurityContext() {
return (SecurityContext) ((HttpSession)getSource()).getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
}
- public HttpSession getSession() {
- return (HttpSession) getSource();
+ @Override
+ public String getId() {
+ return getSession().getId();
}
}
diff --git a/web/src/test/java/org/springframework/security/web/concurrent/ConcurrentSessionFilterTests.java b/web/src/test/java/org/springframework/security/web/concurrent/ConcurrentSessionFilterTests.java
index 45f0f2f7c8..fde20d7bdf 100644
--- a/web/src/test/java/org/springframework/security/web/concurrent/ConcurrentSessionFilterTests.java
+++ b/web/src/test/java/org/springframework/security/web/concurrent/ConcurrentSessionFilterTests.java
@@ -21,8 +21,8 @@ import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockHttpSession;
import org.springframework.security.authentication.concurrent.SessionRegistry;
+import org.springframework.security.authentication.concurrent.SessionRegistryImpl;
import org.springframework.security.web.concurrent.ConcurrentSessionFilter;
-import org.springframework.security.web.concurrent.SessionRegistryImpl;
import javax.servlet.Filter;
import javax.servlet.FilterChain;