SEC-1229: Refactored authentication.concurrent in core, moving classes into core.session

This commit is contained in:
Luke Taylor
2009-10-05 15:51:00 +00:00
parent 2b89ebdfbb
commit acf13c74ca
23 changed files with 119 additions and 150 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -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.

View File

@@ -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");

View File

@@ -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());
/**

View File

@@ -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");

View File

@@ -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;

View File

@@ -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());