diff --git a/core/src/main/java/org/springframework/security/concurrent/ConcurrentSessionFilter.java b/core/src/main/java/org/springframework/security/concurrent/ConcurrentSessionFilter.java
index d9106f2019..062079d97f 100644
--- a/core/src/main/java/org/springframework/security/concurrent/ConcurrentSessionFilter.java
+++ b/core/src/main/java/org/springframework/security/concurrent/ConcurrentSessionFilter.java
@@ -16,36 +16,34 @@
package org.springframework.security.concurrent;
import org.springframework.beans.factory.InitializingBean;
-
+import org.springframework.security.ui.FilterChainOrderUtils;
+import org.springframework.security.ui.SpringSecurityFilter;
import org.springframework.util.Assert;
-import java.io.IOException;
-
-import javax.servlet.Filter;
import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
+import java.io.IOException;
/**
- * Filter required by concurrent session handling package.
This filter performs two functions. First, it calls
- * {@link org.springframework.security.concurrent.SessionRegistry#refreshLastRequest(String)} for each request. That way,
- * registered sessions always have a correct "last update" date/time. Second, it retrieves {@link
- * org.springframework.security.concurrent.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 session is invalidated. The
- * invalidation of the session will also cause the request to redirect to the URL specified, and a {@link
- * org.springframework.security.ui.session.HttpSessionDestroyedEvent} to be published via the {@link
- * org.springframework.security.ui.session.HttpSessionEventPublisher} registered in web.xml.
+ * Filter required by concurrent session handling package.
+ * This filter performs two functions. First, it calls
+ * {@link org.springframework.security.concurrent.SessionRegistry#refreshLastRequest(String)} for each request.
+ * That way, registered sessions always have a correct "last update" date/time. Second, it retrieves
+ * {@link org.springframework.security.concurrent.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 session is invalidated. The invalidation of the session will also cause the
+ * request to redirect to the URL specified, and a
+ * {@link org.springframework.security.ui.session.HttpSessionDestroyedEvent} to be published via the
+ * {@link org.springframework.security.ui.session.HttpSessionEventPublisher} registered in web.xml.
*
* @author Ben Alex
* @version $Id$
*/
-public class ConcurrentSessionFilter implements Filter, InitializingBean {
+public class ConcurrentSessionFilter extends SpringSecurityFilter implements InitializingBean {
//~ Instance fields ================================================================================================
private SessionRegistry sessionRegistry;
@@ -55,23 +53,12 @@ public class ConcurrentSessionFilter implements Filter, InitializingBean {
public void afterPropertiesSet() throws Exception {
Assert.notNull(sessionRegistry, "SessionRegistry required");
- Assert.hasText(expiredUrl, "ExpiredUrl required");
}
- /**
- * Does nothing. We use IoC container lifecycle services instead.
- */
- public void destroy() {}
+ public void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
+ throws IOException, ServletException {
- public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
- throws IOException, ServletException {
- Assert.isInstanceOf(HttpServletRequest.class, request, "Can only process HttpServletRequest");
- Assert.isInstanceOf(HttpServletResponse.class, response, "Can only process HttpServletResponse");
-
- HttpServletRequest httpRequest = (HttpServletRequest) request;
- HttpServletResponse httpResponse = (HttpServletResponse) response;
-
- HttpSession session = httpRequest.getSession(false);
+ HttpSession session = request.getSession(false);
if (session != null) {
SessionInformation info = sessionRegistry.getSessionInformation(session.getId());
@@ -81,8 +68,14 @@ public class ConcurrentSessionFilter implements Filter, InitializingBean {
// Expired - abort processing
session.invalidate();
- String targetUrl = httpRequest.getContextPath() + expiredUrl;
- httpResponse.sendRedirect(httpResponse.encodeRedirectURL(targetUrl));
+ if (expiredUrl != null) {
+ String targetUrl = request.getContextPath() + expiredUrl;
+ response.sendRedirect(response.encodeRedirectURL(targetUrl));
+ } else {
+ response.getWriter().print("This session has been expired (possibly due to multiple concurrent " +
+ "logins being attempted as the same user).");
+ response.flushBuffer();
+ }
return;
} else {
@@ -95,15 +88,6 @@ public class ConcurrentSessionFilter implements Filter, InitializingBean {
chain.doFilter(request, response);
}
- /**
- * Does nothing. We use IoC container lifecycle services instead.
- *
- * @param arg0 ignored
- *
- * @throws ServletException ignored
- */
- public void init(FilterConfig arg0) throws ServletException {}
-
public void setExpiredUrl(String expiredUrl) {
this.expiredUrl = expiredUrl;
}
@@ -111,4 +95,8 @@ public class ConcurrentSessionFilter implements Filter, InitializingBean {
public void setSessionRegistry(SessionRegistry sessionRegistry) {
this.sessionRegistry = sessionRegistry;
}
+
+ public int getOrder() {
+ return FilterChainOrderUtils.CONCURRENT_SESSION_FILTER_ORDER;
+ }
}
diff --git a/core/src/test/java/org/springframework/security/concurrent/ConcurrentSessionFilterTests.java b/core/src/test/java/org/springframework/security/concurrent/ConcurrentSessionFilterTests.java
index bca3a21e66..39e9d7555d 100644
--- a/core/src/test/java/org/springframework/security/concurrent/ConcurrentSessionFilterTests.java
+++ b/core/src/test/java/org/springframework/security/concurrent/ConcurrentSessionFilterTests.java
@@ -40,10 +40,6 @@ import java.util.Date;
public class ConcurrentSessionFilterTests extends TestCase {
//~ Constructors ===================================================================================================
- public ConcurrentSessionFilterTests() {
- super();
- }
-
public ConcurrentSessionFilterTests(String arg0) {
super(arg0);
}
@@ -58,10 +54,6 @@ public class ConcurrentSessionFilterTests extends TestCase {
filter.destroy();
}
- public static void main(String[] args) {
- junit.textui.TestRunner.run(ConcurrentSessionFilterTests.class);
- }
-
public void testDetectsExpiredSessions() throws Exception {
// Setup our HTTP request
MockHttpServletRequest request = new MockHttpServletRequest();
@@ -88,16 +80,27 @@ public class ConcurrentSessionFilterTests extends TestCase {
assertEquals("/expired.jsp", response.getRedirectedUrl());
}
- public void testDetectsMissingExpiredUrl() throws Exception {
- ConcurrentSessionFilter filter = new ConcurrentSessionFilter();
- filter.setSessionRegistry(new SessionRegistryImpl());
+ // As above, but with no expiredUrl set.
+ public void testReturnsExpectedMessageWhenNoExpiredUrlSet() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpSession session = new MockHttpSession();
+ request.setSession(session);
- try {
- filter.afterPropertiesSet();
- fail("Should have thrown IAE");
- } catch (IllegalArgumentException expected) {
- assertTrue(true);
- }
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ MockFilterConfig config = new MockFilterConfig(null, null);
+
+ MockFilterChain chain = new MockFilterChain(false);
+
+ ConcurrentSessionFilter filter = new ConcurrentSessionFilter();
+ SessionRegistry registry = new SessionRegistryImpl();
+ registry.registerNewSession(session.getId(), "principal");
+ registry.getSessionInformation(session.getId()).expireNow();
+ filter.setSessionRegistry(registry);
+
+ executeFilterInContainerSimulator(config, filter, request, response, chain);
+
+ assertEquals("This session has been expired (possibly due to multiple concurrent logins being " +
+ "attempted as the same user).", response.getContentAsString());
}
public void testDetectsMissingSessionRegistry() throws Exception {