Polish SessionInformationExpiredStrategy
* Fix passivity and add tests * Introduce SessionInformationExpiredEvent as a value object * Rename ExpiredSessionStrategy to SessionInformationExpiredStrategy to account for the need of SessionInformation * Switch to Constructor Injection * Move the changes to the xsd to 4.2 xsd instead of 4.1 Issue gh-3808
This commit is contained in:
+75
-18
@@ -17,6 +17,7 @@
|
||||
package org.springframework.security.web.session;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
@@ -29,11 +30,11 @@ import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.session.SessionInformation;
|
||||
import org.springframework.security.core.session.SessionRegistry;
|
||||
import org.springframework.security.web.DefaultRedirectStrategy;
|
||||
import org.springframework.security.web.RedirectStrategy;
|
||||
import org.springframework.security.web.authentication.logout.CompositeLogoutHandler;
|
||||
import org.springframework.security.web.authentication.logout.LogoutHandler;
|
||||
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
|
||||
import org.springframework.security.web.util.UrlUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.filter.GenericFilterBean;
|
||||
|
||||
@@ -49,7 +50,7 @@ import org.springframework.web.filter.GenericFilterBean;
|
||||
* 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. To handle the expired session a call to the {@link ExpiredSessionStrategy} is made.
|
||||
* to invalidate the session. To handle the expired session a call to the {@link SessionInformationExpiredStrategy} is made.
|
||||
* The session invalidation will cause an
|
||||
* {@link org.springframework.security.web.session.HttpSessionDestroyedEvent} to be
|
||||
* published via the
|
||||
@@ -62,12 +63,15 @@ import org.springframework.web.filter.GenericFilterBean;
|
||||
* @author Marten Deinum
|
||||
*/
|
||||
public class ConcurrentSessionFilter extends GenericFilterBean {
|
||||
|
||||
// ~ Instance fields
|
||||
// ================================================================================================
|
||||
|
||||
private final SessionRegistry sessionRegistry;
|
||||
private String expiredUrl;
|
||||
private RedirectStrategy redirectStrategy;
|
||||
private LogoutHandler handlers = new CompositeLogoutHandler(new SecurityContextLogoutHandler());
|
||||
private ExpiredSessionStrategy expiredSessionStrategy;
|
||||
private SessionInformationExpiredStrategy sessionInformationExpiredStrategy;
|
||||
|
||||
// ~ Methods
|
||||
// ========================================================================================================
|
||||
@@ -75,12 +79,42 @@ public class ConcurrentSessionFilter extends GenericFilterBean {
|
||||
public ConcurrentSessionFilter(SessionRegistry sessionRegistry) {
|
||||
Assert.notNull(sessionRegistry, "SessionRegistry required");
|
||||
this.sessionRegistry = sessionRegistry;
|
||||
this.sessionInformationExpiredStrategy = new ResponseBodySessionInformationExpiredStrategy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*
|
||||
* @param sessionRegistry the SessionRegistry to use
|
||||
* @param expiredUrl the URL to redirect to
|
||||
* @deprecated use {@link #ConcurrentSessionFilter(SessionRegistry, SessionInformationExpiredStrategy)} with {@link SimpleRedirectSessionInformationExpiredStrategy} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public ConcurrentSessionFilter(SessionRegistry sessionRegistry, String expiredUrl) {
|
||||
Assert.notNull(sessionRegistry, "SessionRegistry required");
|
||||
Assert.isTrue(expiredUrl == null || UrlUtils.isValidRedirectUrl(expiredUrl),
|
||||
expiredUrl + " isn't a valid redirect URL");
|
||||
this.expiredUrl = expiredUrl;
|
||||
this.sessionRegistry = sessionRegistry;
|
||||
this.expiredSessionStrategy = new SimpleRedirectExpiredSessionStrategy(expiredUrl);
|
||||
this.sessionInformationExpiredStrategy = new SessionInformationExpiredStrategy() {
|
||||
|
||||
@Override
|
||||
public void onExpiredSessionDetected(SessionInformationExpiredEvent event) throws IOException, ServletException {
|
||||
HttpServletRequest request = event.getRequest();
|
||||
HttpServletResponse response = event.getResponse();
|
||||
SessionInformation info = event.getSessionInformation();
|
||||
|
||||
redirectStrategy.sendRedirect(request, response, determineExpiredUrl(request, info));
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
public ConcurrentSessionFilter(SessionRegistry sessionRegistry, SessionInformationExpiredStrategy sessionInformationExpiredStrategy) {
|
||||
Assert.notNull(sessionRegistry, "sessionRegistry required");
|
||||
Assert.notNull(sessionInformationExpiredStrategy, "sessionInformationExpiredStrategy cannot be null");
|
||||
this.sessionRegistry = sessionRegistry;
|
||||
this.sessionInformationExpiredStrategy = sessionInformationExpiredStrategy;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -108,18 +142,7 @@ public class ConcurrentSessionFilter extends GenericFilterBean {
|
||||
}
|
||||
doLogout(request, response);
|
||||
|
||||
if (this.expiredSessionStrategy != null) {
|
||||
this.expiredSessionStrategy.onExpiredSessionDetected(request, response);
|
||||
|
||||
return;
|
||||
}
|
||||
else {
|
||||
response.getWriter().print(
|
||||
"This session has been expired (possibly due to multiple concurrent "
|
||||
+ "logins being attempted as the same user).");
|
||||
response.flushBuffer();
|
||||
}
|
||||
|
||||
this.sessionInformationExpiredStrategy.onExpiredSessionDetected(new SessionInformationExpiredEvent(info, request, response));
|
||||
return;
|
||||
}
|
||||
else {
|
||||
@@ -132,6 +155,17 @@ public class ConcurrentSessionFilter extends GenericFilterBean {
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the URL for expiration
|
||||
* @param request the HttpServletRequest
|
||||
* @param info the {@link SessionInformation}
|
||||
* @return the URL for expiration
|
||||
* @deprecated Use {@link #ConcurrentSessionFilter(SessionRegistry, SessionInformationExpiredStrategy)} instead.
|
||||
*/
|
||||
protected String determineExpiredUrl(HttpServletRequest request,
|
||||
SessionInformation info) {
|
||||
return expiredUrl;
|
||||
}
|
||||
|
||||
private void doLogout(HttpServletRequest request, HttpServletResponse response) {
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
@@ -143,7 +177,30 @@ public class ConcurrentSessionFilter extends GenericFilterBean {
|
||||
this.handlers = new CompositeLogoutHandler(handlers);
|
||||
}
|
||||
|
||||
public void setExpiredSessionStrategy(ExpiredSessionStrategy expiredSessionStrategy) {
|
||||
this.expiredSessionStrategy=expiredSessionStrategy;
|
||||
/**
|
||||
* Sets the {@link RedirectStrategy} used with {@link #ConcurrentSessionFilter(SessionRegistry, String)}
|
||||
* @param redirectStrategy the {@link RedirectStrategy} to use
|
||||
* @deprecated use {@link #ConcurrentSessionFilter(SessionRegistry, SessionInformationExpiredStrategy)} instead.
|
||||
*/
|
||||
public void setRedirectStrategy(RedirectStrategy redirectStrategy) {
|
||||
this.redirectStrategy = redirectStrategy;
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link SessionInformationExpiredStrategy} that writes an error message to the response body.
|
||||
* @author Rob Winch
|
||||
* @since 4.2
|
||||
*/
|
||||
private static final class ResponseBodySessionInformationExpiredStrategy
|
||||
implements SessionInformationExpiredStrategy {
|
||||
@Override
|
||||
public void onExpiredSessionDetected(SessionInformationExpiredEvent event)
|
||||
throws IOException, ServletException {
|
||||
HttpServletResponse response = event.getResponse();
|
||||
response.getWriter().print(
|
||||
"This session has been expired (possibly due to multiple concurrent "
|
||||
+ "logins being attempted as the same user).");
|
||||
response.flushBuffer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2012-2016 the original author or authors.
|
||||
*
|
||||
* 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.web.session;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.security.core.session.SessionInformation;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* An event for when a {@link SessionInformation} is expired.
|
||||
* @author Rob Winch
|
||||
* @since 4.2
|
||||
*/
|
||||
public final class SessionInformationExpiredEvent extends ApplicationEvent {
|
||||
|
||||
private HttpServletRequest request;
|
||||
private HttpServletResponse response;
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*
|
||||
* @param sessionInformation the SessionInformation that is expired
|
||||
* @param request the HttpServletRequest
|
||||
* @param response the HttpServletResponse
|
||||
*/
|
||||
public SessionInformationExpiredEvent(SessionInformation sessionInformation, HttpServletRequest request, HttpServletResponse response) {
|
||||
super(sessionInformation);
|
||||
Assert.notNull(request, "request cannot be null");
|
||||
Assert.notNull(response, "response cannot be null");
|
||||
this.request = request;
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the request
|
||||
*/
|
||||
public HttpServletRequest getRequest() {
|
||||
return request;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the response
|
||||
*/
|
||||
public HttpServletResponse getResponse() {
|
||||
return response;
|
||||
}
|
||||
|
||||
public SessionInformation getSessionInformation() {
|
||||
return (SessionInformation) getSource();
|
||||
}
|
||||
}
|
||||
+5
-6
@@ -16,20 +16,19 @@
|
||||
package org.springframework.security.web.session;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* Determines the behaviour of the {@code ConcurrentSessionFilter} when an expired session
|
||||
* is detected in the {@code ConcurrentSessionFilter}.
|
||||
*
|
||||
* @author Marten Deinum
|
||||
* @since 4.1.0
|
||||
* @author Rob Winch
|
||||
* @since 4.2.0
|
||||
*/
|
||||
public interface ExpiredSessionStrategy {
|
||||
public interface SessionInformationExpiredStrategy {
|
||||
|
||||
void onExpiredSessionDetected(HttpServletRequest request, HttpServletResponse response)
|
||||
void onExpiredSessionDetected(SessionInformationExpiredEvent eventØ)
|
||||
throws IOException, ServletException;
|
||||
|
||||
}
|
||||
+7
-9
@@ -16,11 +16,10 @@
|
||||
package org.springframework.security.web.session;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.security.web.DefaultRedirectStrategy;
|
||||
import org.springframework.security.web.RedirectStrategy;
|
||||
import org.springframework.security.web.util.UrlUtils;
|
||||
@@ -31,28 +30,27 @@ import org.springframework.util.Assert;
|
||||
* {@code ConcurrentSessionFilter}.
|
||||
*
|
||||
* @author Marten Deinum
|
||||
* @since 4.1.0
|
||||
* @since 4.2.0
|
||||
*/
|
||||
public final class SimpleRedirectExpiredSessionStrategy implements ExpiredSessionStrategy {
|
||||
public final class SimpleRedirectSessionInformationExpiredStrategy implements SessionInformationExpiredStrategy {
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
private final String destinationUrl;
|
||||
private final RedirectStrategy redirectStrategy;
|
||||
|
||||
public SimpleRedirectExpiredSessionStrategy(String invalidSessionUrl) {
|
||||
public SimpleRedirectSessionInformationExpiredStrategy(String invalidSessionUrl) {
|
||||
this(invalidSessionUrl, new DefaultRedirectStrategy());
|
||||
}
|
||||
|
||||
public SimpleRedirectExpiredSessionStrategy(String invalidSessionUrl, RedirectStrategy redirectStrategy) {
|
||||
public SimpleRedirectSessionInformationExpiredStrategy(String invalidSessionUrl, RedirectStrategy redirectStrategy) {
|
||||
Assert.isTrue(UrlUtils.isValidRedirectUrl(invalidSessionUrl),
|
||||
"url must start with '/' or with 'http(s)'");
|
||||
this.destinationUrl=invalidSessionUrl;
|
||||
this.redirectStrategy=redirectStrategy;
|
||||
}
|
||||
|
||||
public void onExpiredSessionDetected(HttpServletRequest request,
|
||||
HttpServletResponse response) throws IOException {
|
||||
public void onExpiredSessionDetected(SessionInformationExpiredEvent event) throws IOException {
|
||||
logger.debug("Redirecting to '" + destinationUrl + "'");
|
||||
redirectStrategy.sendRedirect(request, response, destinationUrl);
|
||||
redirectStrategy.sendRedirect(event.getRequest(), event.getResponse(), destinationUrl);
|
||||
}
|
||||
|
||||
}
|
||||
+211
-9
@@ -17,21 +17,37 @@
|
||||
package org.springframework.security.web.concurrent;
|
||||
|
||||
import java.util.Date;
|
||||
import javax.servlet.FilterChain;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.mock.web.MockFilterChain;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.session.SessionInformation;
|
||||
import org.springframework.security.core.session.SessionRegistry;
|
||||
import org.springframework.security.core.session.SessionRegistryImpl;
|
||||
import org.springframework.security.web.RedirectStrategy;
|
||||
import org.springframework.security.web.authentication.logout.LogoutHandler;
|
||||
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
|
||||
import org.springframework.security.web.session.ConcurrentSessionFilter;
|
||||
import org.springframework.security.web.session.SimpleRedirectExpiredSessionStrategy;
|
||||
import org.springframework.security.web.session.SessionInformationExpiredStrategy;
|
||||
import org.springframework.security.web.session.SimpleRedirectSessionInformationExpiredStrategy;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* Tests {@link ConcurrentSessionFilter}.
|
||||
@@ -41,6 +57,33 @@ import static org.mockito.Mockito.*;
|
||||
*/
|
||||
public class ConcurrentSessionFilterTests {
|
||||
|
||||
@After
|
||||
public void cleanup() {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void constructorSessionRegistryWhenSessionRegistryNullThenExceptionThrown() {
|
||||
new ConcurrentSessionFilter(null);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void constructorSessionRegistryExpiresUrlWhenInvalidUrlThenExceptionThrown() {
|
||||
new ConcurrentSessionFilter(new SessionRegistryImpl(), "oops");
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void constructorSessionRegistryExpiresUrlWhenSessionRegistryNullThenExceptionThrown() {
|
||||
new ConcurrentSessionFilter(null, "/expired");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void constructorSessionRegistrySessionInformationExpiredStrategyWhenStrategyIsNullThenThrowsException() {
|
||||
new ConcurrentSessionFilter(new SessionRegistryImpl(), (SessionInformationExpiredStrategy) null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void detectsExpiredSessions() throws Exception {
|
||||
// Setup our HTTP request
|
||||
@@ -56,9 +99,8 @@ public class ConcurrentSessionFilterTests {
|
||||
|
||||
// Setup our test fixture and registry to want this session to be expired
|
||||
|
||||
SimpleRedirectExpiredSessionStrategy expiredSessionStrategy = new SimpleRedirectExpiredSessionStrategy("/expired.jsp");
|
||||
ConcurrentSessionFilter filter = new ConcurrentSessionFilter(registry);
|
||||
filter.setExpiredSessionStrategy(expiredSessionStrategy);
|
||||
SimpleRedirectSessionInformationExpiredStrategy expiredSessionStrategy = new SimpleRedirectSessionInformationExpiredStrategy("/expired.jsp");
|
||||
ConcurrentSessionFilter filter = new ConcurrentSessionFilter(registry, expiredSessionStrategy);
|
||||
filter.setLogoutHandlers(new LogoutHandler[] { new SecurityContextLogoutHandler() });
|
||||
filter.afterPropertiesSet();
|
||||
|
||||
@@ -110,9 +152,8 @@ public class ConcurrentSessionFilterTests {
|
||||
// Setup our test fixture
|
||||
SessionRegistry registry = new SessionRegistryImpl();
|
||||
registry.registerNewSession(session.getId(), "principal");
|
||||
SimpleRedirectExpiredSessionStrategy expiredSessionStrategy = new SimpleRedirectExpiredSessionStrategy("/expired.jsp");
|
||||
ConcurrentSessionFilter filter = new ConcurrentSessionFilter(registry);
|
||||
filter.setExpiredSessionStrategy(expiredSessionStrategy);
|
||||
SimpleRedirectSessionInformationExpiredStrategy expiredSessionStrategy = new SimpleRedirectSessionInformationExpiredStrategy("/expired.jsp");
|
||||
ConcurrentSessionFilter filter = new ConcurrentSessionFilter(registry, expiredSessionStrategy);
|
||||
|
||||
Date lastRequest = registry.getSessionInformation(session.getId()).getLastRequest();
|
||||
|
||||
@@ -123,4 +164,165 @@ public class ConcurrentSessionFilterTests {
|
||||
verify(fc).doFilter(request, response);
|
||||
assertThat(registry.getSessionInformation(session.getId()).getLastRequest().after(lastRequest)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doFilterWhenNoSessionThenChainIsContinued() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
RedirectStrategy redirect = mock(RedirectStrategy.class);
|
||||
SessionRegistry registry = mock(SessionRegistry.class);
|
||||
SessionInformation information = new SessionInformation("user", "sessionId", new Date(System.currentTimeMillis() - 1000));
|
||||
information.expireNow();
|
||||
when(registry.getSessionInformation(anyString())).thenReturn(information);
|
||||
|
||||
|
||||
String expiredUrl = "/expired";
|
||||
ConcurrentSessionFilter filter = new ConcurrentSessionFilter(registry,
|
||||
expiredUrl);
|
||||
filter.setRedirectStrategy(redirect);
|
||||
|
||||
MockFilterChain chain = new MockFilterChain();
|
||||
|
||||
filter.doFilter(request, response, chain);
|
||||
|
||||
assertThat(chain.getRequest()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doFilterWhenNoSessionInformationThenChainIsContinued() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setSession(new MockHttpSession());
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
RedirectStrategy redirect = mock(RedirectStrategy.class);
|
||||
SessionRegistry registry = mock(SessionRegistry.class);
|
||||
|
||||
|
||||
String expiredUrl = "/expired";
|
||||
ConcurrentSessionFilter filter = new ConcurrentSessionFilter(registry,
|
||||
expiredUrl);
|
||||
filter.setRedirectStrategy(redirect);
|
||||
|
||||
MockFilterChain chain = new MockFilterChain();
|
||||
|
||||
filter.doFilter(request, response, chain);
|
||||
|
||||
assertThat(chain.getRequest()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doFilterWhenCustomRedirectStrategyThenCustomRedirectStrategyUsed() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpSession session = new MockHttpSession();
|
||||
request.setSession(session);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
RedirectStrategy redirect = mock(RedirectStrategy.class);
|
||||
SessionRegistry registry = mock(SessionRegistry.class);
|
||||
SessionInformation information = new SessionInformation("user", "sessionId", new Date(System.currentTimeMillis() - 1000));
|
||||
information.expireNow();
|
||||
when(registry.getSessionInformation(anyString())).thenReturn(information);
|
||||
|
||||
|
||||
String expiredUrl = "/expired";
|
||||
ConcurrentSessionFilter filter = new ConcurrentSessionFilter(registry,
|
||||
expiredUrl);
|
||||
filter.setRedirectStrategy(redirect);
|
||||
|
||||
filter.doFilter(request, response, new MockFilterChain());
|
||||
|
||||
verify(redirect).sendRedirect(request, response, expiredUrl);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doFilterWhenOverrideThenCustomRedirectStrategyUsed() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpSession session = new MockHttpSession();
|
||||
request.setSession(session);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
RedirectStrategy redirect = mock(RedirectStrategy.class);
|
||||
SessionRegistry registry = mock(SessionRegistry.class);
|
||||
SessionInformation information = new SessionInformation("user", "sessionId", new Date(System.currentTimeMillis() - 1000));
|
||||
information.expireNow();
|
||||
when(registry.getSessionInformation(anyString())).thenReturn(information);
|
||||
|
||||
|
||||
final String expiredUrl = "/expired";
|
||||
ConcurrentSessionFilter filter = new ConcurrentSessionFilter(registry,
|
||||
expiredUrl + "will-be-overrridden") {
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.security.web.session.ConcurrentSessionFilter#determineExpiredUrl(javax.servlet.http.HttpServletRequest, org.springframework.security.core.session.SessionInformation)
|
||||
*/
|
||||
@Override
|
||||
protected String determineExpiredUrl(HttpServletRequest request,
|
||||
SessionInformation info) {
|
||||
return expiredUrl;
|
||||
}
|
||||
|
||||
};
|
||||
filter.setRedirectStrategy(redirect);
|
||||
|
||||
filter.doFilter(request, response, new MockFilterChain());
|
||||
|
||||
verify(redirect).sendRedirect(request, response, expiredUrl);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doFilterWhenNoExpiredUrlThenResponseWritten() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpSession session = new MockHttpSession();
|
||||
request.setSession(session);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
SessionRegistry registry = mock(SessionRegistry.class);
|
||||
SessionInformation information = new SessionInformation("user", "sessionId", new Date(System.currentTimeMillis() - 1000));
|
||||
information.expireNow();
|
||||
when(registry.getSessionInformation(anyString())).thenReturn(information);
|
||||
|
||||
|
||||
ConcurrentSessionFilter filter = new ConcurrentSessionFilter(registry);
|
||||
|
||||
filter.doFilter(request, response, new MockFilterChain());
|
||||
|
||||
assertThat(response.getContentAsString()).contains(
|
||||
"This session has been expired (possibly due to multiple concurrent logins being attempted as the same user).");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doFilterWhenCustomLogoutHandlersThenHandlersUsed() throws Exception {
|
||||
LogoutHandler handler = mock(LogoutHandler.class);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpSession session = new MockHttpSession();
|
||||
request.setSession(session);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
SessionRegistry registry = mock(SessionRegistry.class);
|
||||
SessionInformation information = new SessionInformation("user", "sessionId", new Date(System.currentTimeMillis() - 1000));
|
||||
information.expireNow();
|
||||
when(registry.getSessionInformation(anyString())).thenReturn(information);
|
||||
|
||||
|
||||
ConcurrentSessionFilter filter = new ConcurrentSessionFilter(registry);
|
||||
filter.setLogoutHandlers(new LogoutHandler[] { handler } );
|
||||
|
||||
filter.doFilter(request, response, new MockFilterChain());
|
||||
|
||||
verify(handler).logout(eq(request), eq(response), any(Authentication.class));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void setLogoutHandlersWhenNullThenThrowsException() {
|
||||
ConcurrentSessionFilter filter = new ConcurrentSessionFilter(new SessionRegistryImpl());
|
||||
|
||||
filter.setLogoutHandlers(null);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void setLogoutHandlersWhenEmptyThenThrowsException() {
|
||||
ConcurrentSessionFilter filter = new ConcurrentSessionFilter(new SessionRegistryImpl());
|
||||
|
||||
filter.setLogoutHandlers(new LogoutHandler[0]);
|
||||
}
|
||||
}
|
||||
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2012-2016 the original author or authors.
|
||||
*
|
||||
* 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.web.session;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.core.session.SessionInformation;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
* @since 4.2
|
||||
*/
|
||||
public class SessionInformationExpiredEventTests {
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void constructorWhenSessionInformationNullThenThrowsException() {
|
||||
new SessionInformationExpiredEvent(null, new MockHttpServletRequest(), new MockHttpServletResponse());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void constructorWhenRequestNullThenThrowsException() {
|
||||
new SessionInformationExpiredEvent(new SessionInformation("fake", "sessionId", new Date()), null, new MockHttpServletResponse());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void constructorWhenResponseNullThenThrowsException() {
|
||||
new SessionInformationExpiredEvent(new SessionInformation("fake", "sessionId", new Date()), new MockHttpServletRequest(), null);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user