SEC-1229: Added failure handler to the SessionManagementFilter to deal with concurrent login errors.

This commit is contained in:
Luke Taylor 2009-09-29 16:14:31 +00:00
parent bf39a5bb36
commit 1ead8472d1
2 changed files with 23 additions and 5 deletions

View File

@ -9,7 +9,6 @@ import javax.servlet.http.HttpSession;
import org.springframework.context.MessageSource; import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware; import org.springframework.context.MessageSourceAware;
import org.springframework.context.support.MessageSourceAccessor; 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.SessionInformation;
import org.springframework.security.authentication.concurrent.SessionRegistry; import org.springframework.security.authentication.concurrent.SessionRegistry;
import org.springframework.security.core.Authentication; 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 allowableSessions the number of concurrent sessions the user is allowed to have
* @param registry an instance of the <code>SessionRegistry</code> for subclass use * @param registry an instance of the <code>SessionRegistry</code> for subclass use
* *
* @throws ConcurrentLoginException if the
*/ */
protected void allowableSessionsExceeded(List<SessionInformation> sessions, int allowableSessions, protected void allowableSessionsExceeded(List<SessionInformation> sessions, int allowableSessions,
SessionRegistry registry) { SessionRegistry registry) {
if (exceptionIfMaximumExceeded || (sessions == null)) { if (exceptionIfMaximumExceeded || (sessions == null)) {
throw new ConcurrentLoginException(messages.getMessage("ConcurrentSessionControllerImpl.exceededAllowed", throw new SessionAuthenticationException(messages.getMessage("ConcurrentSessionControllerImpl.exceededAllowed",
new Object[] {new Integer(allowableSessions)}, new Object[] {new Integer(allowableSessions)},
"Maximum sessions of {0} for this principal exceeded")); "Maximum sessions of {0} for this principal exceeded"));
} }

View File

@ -15,6 +15,8 @@ import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.DefaultRedirectStrategy; import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy; 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.security.web.context.SecurityContextRepository;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.web.filter.GenericFilterBean; import org.springframework.web.filter.GenericFilterBean;
@ -40,6 +42,7 @@ public class SessionManagementFilter extends GenericFilterBean {
private SessionAuthenticationStrategy sessionStrategy = new DefaultSessionAuthenticationStrategy(); private SessionAuthenticationStrategy sessionStrategy = new DefaultSessionAuthenticationStrategy();
private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl(); private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl();
private String invalidSessionUrl; private String invalidSessionUrl;
private AuthenticationFailureHandler failureHandler = new SimpleUrlAuthenticationFailureHandler();
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
public SessionManagementFilter(SecurityContextRepository securityContextRepository) { public SessionManagementFilter(SecurityContextRepository securityContextRepository) {
@ -67,13 +70,19 @@ public class SessionManagementFilter extends GenericFilterBean {
sessionStrategy.onAuthentication(authentication, request, response); sessionStrategy.onAuthentication(authentication, request, response);
} catch (SessionAuthenticationException e) { } catch (SessionAuthenticationException e) {
// The session strategy can reject the authentication // 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(); SecurityContextHolder.clearContext();
failureHandler.onAuthenticationFailure(request, response, e);
return;
} }
} else { } else {
// No security context or authentication present. Check for a session timeout // No security context or authentication present. Check for a session timeout
if (request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid()) { if (request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid()) {
logger.debug("Requested session ID" + request.getRequestedSessionId() + " is invalid.");
if (invalidSessionUrl != null) { if (invalidSessionUrl != null) {
logger.debug("Redirecting to '" + invalidSessionUrl + "'");
redirectStrategy.sendRedirect(request, response, 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. * If the property is not set, no action will be taken.
* *
* @param invalidSessionUrl * @param invalidSessionUrl
@ -104,6 +113,17 @@ public class SessionManagementFilter extends GenericFilterBean {
this.invalidSessionUrl = invalidSessionUrl; this.invalidSessionUrl = invalidSessionUrl;
} }
/**
* The handler which will be invoked if the <tt>AuthenticatedSessionStrategy</tt> raises a
* <tt>SessionAuthenticationException</tt>, 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) { public void setRedirectStrategy(RedirectStrategy redirectStrategy) {
this.redirectStrategy = redirectStrategy; this.redirectStrategy = redirectStrategy;
} }