SEC-1229: Refactored authentication.concurrent in core, moving classes into core.session
This commit is contained in:
@@ -37,8 +37,8 @@ import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.SpringSecurityMessageSource;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.web.session.SessionAuthenticationStrategy;
|
||||
import org.springframework.security.web.session.NullAuthenticatedSessionStrategy;
|
||||
import org.springframework.security.web.session.SessionAuthenticationStrategy;
|
||||
import org.springframework.security.web.util.UrlUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.filter.GenericFilterBean;
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
package org.springframework.security.web.authentication;
|
||||
|
||||
import org.springframework.security.authentication.concurrent.SessionIdentifierAware;
|
||||
import org.springframework.security.core.session.SessionIdentifierAware;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
@@ -25,10 +25,10 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
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.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.LogoutHandler;
|
||||
@@ -42,9 +42,9 @@ import org.springframework.web.filter.GenericFilterBean;
|
||||
* Filter required by concurrent session handling package.
|
||||
* <p>
|
||||
* 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 <code>SessionRegistry</code>
|
||||
* {@link org.springframework.security.core.session.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 configured logout handlers will be called (as happens with
|
||||
* {@link org.springframework.security.web.authentication.logout.LogoutFilter}), typically to invalidate the session.
|
||||
|
||||
@@ -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 <tt>maximumSessions</tt> value.
|
||||
* The {@link SessionRegistry} is used as the source of data on authenticated users and session data.
|
||||
* <p>
|
||||
* If a user has reached the maximum number of permitted sessions, the behaviour depends on the
|
||||
* <tt>exceptionIfMaxExceeded</tt> property. The default behaviour is to expired the least recently used session, which
|
||||
* will be invalidated by the {@link ConcurrentSessionFilter} if accessed again. If <tt>exceptionIfMaxExceeded</tt> is
|
||||
* set to <tt>true</tt>, however, the user will be prevented from starting a new authenticated session.
|
||||
* <p>
|
||||
* 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<SessionInformation> sessions, int allowableSessions,
|
||||
SessionRegistry registry) {
|
||||
SessionRegistry registry) throws SessionAuthenticationException {
|
||||
if (exceptionIfMaximumExceeded || (sessions == null)) {
|
||||
throw new SessionAuthenticationException(messages.getMessage("ConcurrentSessionControllerImpl.exceededAllowed",
|
||||
new Object[] {new Integer(allowableSessions)},
|
||||
@@ -133,10 +149,22 @@ public class ConcurrentSessionControlStrategy extends DefaultSessionAuthenticati
|
||||
sessionRegistry.registerNewSession(newSession.getId(), auth.getPrincipal());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the <tt>exceptionIfMaximumExceeded</tt> property, which determines whether the user should be prevented
|
||||
* from opening more sessions than allowed. If set to <tt>true</tt>, a <tt>SessionAuthenticationException</tt>
|
||||
* will be raised.
|
||||
*
|
||||
* @param exceptionIfMaximumExceeded defaults to <tt>false</tt>.
|
||||
*/
|
||||
public void setExceptionIfMaximumExceeded(boolean exceptionIfMaximumExceeded) {
|
||||
this.exceptionIfMaximumExceeded = exceptionIfMaximumExceeded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the <tt>maxSessions</tt> property. The default value is 1. Use -1 for unlimited sessions.
|
||||
*
|
||||
* @param maximumSessions the maximimum number of permitted sessions a user can have open simultaneously.
|
||||
*/
|
||||
public void setMaximumSessions(int maximumSessions) {
|
||||
Assert.isTrue(maximumSessions != 0,
|
||||
"MaximumLogins must be either -1 to allow unlimited logins, or a positive integer to specify a maximum");
|
||||
|
||||
@@ -32,7 +32,7 @@ import org.springframework.security.web.savedrequest.DefaultSavedRequest;
|
||||
* @version $Id$
|
||||
* @since 3.0
|
||||
*/
|
||||
public class DefaultSessionAuthenticationStrategy implements SessionAuthenticationStrategy {
|
||||
public class SessionFixationProtectionStrategy implements SessionAuthenticationStrategy {
|
||||
protected final Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
/**
|
||||
@@ -39,7 +39,7 @@ public class SessionManagementFilter extends GenericFilterBean {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private final SecurityContextRepository securityContextRepository;
|
||||
private SessionAuthenticationStrategy sessionStrategy = new DefaultSessionAuthenticationStrategy();
|
||||
private SessionAuthenticationStrategy sessionStrategy = new SessionFixationProtectionStrategy();
|
||||
private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl();
|
||||
private String invalidSessionUrl;
|
||||
private AuthenticationFailureHandler failureHandler = new SimpleUrlAuthenticationFailureHandler();
|
||||
@@ -96,7 +96,7 @@ public class SessionManagementFilter extends GenericFilterBean {
|
||||
* Sets the strategy object which handles the session management behaviour when a
|
||||
* user has been authenticated during the current request.
|
||||
*
|
||||
* @param sessionStrategy the strategy object. If not set, a {@link DefaultSessionAuthenticationStrategy} is used.
|
||||
* @param sessionStrategy the strategy object. If not set, a {@link SessionFixationProtectionStrategy} is used.
|
||||
*/
|
||||
public void setSessionAuthenticationStrategy(SessionAuthenticationStrategy sessionStrategy) {
|
||||
Assert.notNull(sessionStrategy, "authenticatedSessionStratedy must not be null");
|
||||
|
||||
@@ -13,15 +13,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.web.authentication;
|
||||
package org.springframework.security.web.concurrent;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.springframework.mock.web.MockFilterConfig;
|
||||
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.core.session.SessionRegistry;
|
||||
import org.springframework.security.core.session.SessionRegistryImpl;
|
||||
import org.springframework.security.web.authentication.concurrent.ConcurrentSessionFilter;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
@@ -21,7 +21,7 @@ public class DefaultSessionAuthenticationStrategyTests {
|
||||
|
||||
@Test
|
||||
public void newSessionShouldNotBeCreatedIfNoSessionExistsAndAlwaysCreateIsFalse() throws Exception {
|
||||
DefaultSessionAuthenticationStrategy strategy = new DefaultSessionAuthenticationStrategy();
|
||||
SessionFixationProtectionStrategy strategy = new SessionFixationProtectionStrategy();
|
||||
HttpServletRequest request = new MockHttpServletRequest();
|
||||
|
||||
strategy.onAuthentication(mock(Authentication.class), request, new MockHttpServletResponse());
|
||||
@@ -31,7 +31,7 @@ public class DefaultSessionAuthenticationStrategyTests {
|
||||
|
||||
@Test
|
||||
public void newSessionIsCreatedIfSessionAlreadyExists() throws Exception {
|
||||
DefaultSessionAuthenticationStrategy strategy = new DefaultSessionAuthenticationStrategy();
|
||||
SessionFixationProtectionStrategy strategy = new SessionFixationProtectionStrategy();
|
||||
HttpServletRequest request = new MockHttpServletRequest();
|
||||
String sessionId = request.getSession().getId();
|
||||
|
||||
@@ -43,7 +43,7 @@ public class DefaultSessionAuthenticationStrategyTests {
|
||||
// See SEC-1077
|
||||
@Test
|
||||
public void onlySavedRequestAttributeIsMigratedIfMigrateAttributesIsFalse() throws Exception {
|
||||
DefaultSessionAuthenticationStrategy strategy = new DefaultSessionAuthenticationStrategy();
|
||||
SessionFixationProtectionStrategy strategy = new SessionFixationProtectionStrategy();
|
||||
strategy.setMigrateSessionAttributes(false);
|
||||
HttpServletRequest request = new MockHttpServletRequest();
|
||||
HttpSession session = request.getSession();
|
||||
@@ -58,7 +58,7 @@ public class DefaultSessionAuthenticationStrategyTests {
|
||||
|
||||
@Test
|
||||
public void sessionIsCreatedIfAlwaysCreateTrue() throws Exception {
|
||||
DefaultSessionAuthenticationStrategy strategy = new DefaultSessionAuthenticationStrategy();
|
||||
SessionFixationProtectionStrategy strategy = new SessionFixationProtectionStrategy();
|
||||
strategy.setAlwaysCreateSession(true);
|
||||
HttpServletRequest request = new MockHttpServletRequest();
|
||||
strategy.onAuthentication(mock(Authentication.class), request, new MockHttpServletResponse());
|
||||
|
||||
Reference in New Issue
Block a user