SEC-585: Made expiredUrl optional.
Also implemented Ordered interface for use in namespace configuration.
This commit is contained in:
parent
55ef50a4df
commit
3d9ea49d19
|
@ -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.<p>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 <code>SessionRegistry</code> 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 <code>web.xml</code>.</p>
|
||||
* Filter required by concurrent session handling package.
|
||||
* <p>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 <code>SessionRegistry</code>
|
||||
* 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 <code>web.xml</code>.</p>
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue