From 1ead8472d17b242ccda8d5308b368d5d79e247eb Mon Sep 17 00:00:00 2001 From: Luke Taylor Date: Tue, 29 Sep 2009 16:14:31 +0000 Subject: [PATCH] SEC-1229: Added failure handler to the SessionManagementFilter to deal with concurrent login errors. --- ...onControlAuthenticatedSessionStrategy.java | 4 +--- .../web/session/SessionManagementFilter.java | 24 +++++++++++++++++-- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/web/src/main/java/org/springframework/security/web/session/ConcurrentSessionControlAuthenticatedSessionStrategy.java b/web/src/main/java/org/springframework/security/web/session/ConcurrentSessionControlAuthenticatedSessionStrategy.java index d90a77b213..5533971a44 100644 --- a/web/src/main/java/org/springframework/security/web/session/ConcurrentSessionControlAuthenticatedSessionStrategy.java +++ b/web/src/main/java/org/springframework/security/web/session/ConcurrentSessionControlAuthenticatedSessionStrategy.java @@ -9,7 +9,6 @@ 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.ConcurrentLoginException; import org.springframework.security.authentication.concurrent.SessionInformation; import org.springframework.security.authentication.concurrent.SessionRegistry; import org.springframework.security.core.Authentication; @@ -105,12 +104,11 @@ public class ConcurrentSessionControlAuthenticatedSessionStrategy extends Defaul * @param allowableSessions the number of concurrent sessions the user is allowed to have * @param registry an instance of the SessionRegistry for subclass use * - * @throws ConcurrentLoginException if the */ protected void allowableSessionsExceeded(List sessions, int allowableSessions, SessionRegistry registry) { if (exceptionIfMaximumExceeded || (sessions == null)) { - throw new ConcurrentLoginException(messages.getMessage("ConcurrentSessionControllerImpl.exceededAllowed", + throw new SessionAuthenticationException(messages.getMessage("ConcurrentSessionControllerImpl.exceededAllowed", new Object[] {new Integer(allowableSessions)}, "Maximum sessions of {0} for this principal exceeded")); } diff --git a/web/src/main/java/org/springframework/security/web/session/SessionManagementFilter.java b/web/src/main/java/org/springframework/security/web/session/SessionManagementFilter.java index 7961fde51c..c0753ecd5a 100644 --- a/web/src/main/java/org/springframework/security/web/session/SessionManagementFilter.java +++ b/web/src/main/java/org/springframework/security/web/session/SessionManagementFilter.java @@ -15,6 +15,8 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.DefaultRedirectStrategy; import org.springframework.security.web.RedirectStrategy; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; +import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; import org.springframework.security.web.context.SecurityContextRepository; import org.springframework.util.Assert; import org.springframework.web.filter.GenericFilterBean; @@ -40,6 +42,7 @@ public class SessionManagementFilter extends GenericFilterBean { private SessionAuthenticationStrategy sessionStrategy = new DefaultSessionAuthenticationStrategy(); private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl(); private String invalidSessionUrl; + private AuthenticationFailureHandler failureHandler = new SimpleUrlAuthenticationFailureHandler(); private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); public SessionManagementFilter(SecurityContextRepository securityContextRepository) { @@ -67,13 +70,19 @@ public class SessionManagementFilter extends GenericFilterBean { sessionStrategy.onAuthentication(authentication, request, response); } catch (SessionAuthenticationException e) { // The session strategy can reject the authentication - logger.debug("SessionAuthenticationStrategy rejected the authentication object",e); + logger.debug("SessionAuthenticationStrategy rejected the authentication object", e); SecurityContextHolder.clearContext(); + failureHandler.onAuthenticationFailure(request, response, e); + + return; } } else { // No security context or authentication present. Check for a session timeout if (request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid()) { + logger.debug("Requested session ID" + request.getRequestedSessionId() + " is invalid."); + if (invalidSessionUrl != null) { + logger.debug("Redirecting to '" + invalidSessionUrl + "'"); redirectStrategy.sendRedirect(request, response, invalidSessionUrl); } } @@ -95,7 +104,7 @@ public class SessionManagementFilter extends GenericFilterBean { } /** - * Sets the URL to which the response should be redirected if the user agent request and invalid session Id. + * Sets the URL to which the response should be redirected if the user agent requests an invalid session Id. * If the property is not set, no action will be taken. * * @param invalidSessionUrl @@ -104,6 +113,17 @@ public class SessionManagementFilter extends GenericFilterBean { this.invalidSessionUrl = invalidSessionUrl; } + /** + * The handler which will be invoked if the AuthenticatedSessionStrategy raises a + * SessionAuthenticationException, indicating that the user is not allowed to be authenticated for this + * session (typically because they already have too many sessions open). + * + */ + public void setAuthenticationFailureHandler(AuthenticationFailureHandler failureHandler) { + Assert.notNull(failureHandler, "failureHandler cannot be null"); + this.failureHandler = failureHandler; + } + public void setRedirectStrategy(RedirectStrategy redirectStrategy) { this.redirectStrategy = redirectStrategy; }