SEC-539: Altered storeSecurityContextInSession to take the SecurityContext as a parameter rather than calling SecurityContextHolder.getContext(). This allows SecurityContextHolder.clearContext() to be called immediately after reading the context in the finally block of doFilter().

This commit is contained in:
Luke Taylor 2007-08-28 21:58:30 +00:00
parent fa63d8ecfb
commit 3dd0716611
1 changed files with 34 additions and 21 deletions

View File

@ -245,17 +245,18 @@ public class HttpSessionContextIntegrationFilter implements InitializingBean, Fi
throw se; throw se;
} }
finally { finally {
// do clean up, even if there was an exception SecurityContext contextAfterChainExecution = SecurityContextHolder.getContext();
// Store context back to HttpSession
storeSecurityContextInSession(request, httpSessionExistedAtStartOfRequest, contextHashWhenChainProceeded); // Crucial removal of SecurityContextHolder contents - do this before anything else.
SecurityContextHolder.clearContext();
request.removeAttribute(FILTER_APPLIED); request.removeAttribute(FILTER_APPLIED);
// Remove SecurityContextHolder contents storeSecurityContextInSession(contextAfterChainExecution, request,
SecurityContextHolder.clearContext(); httpSessionExistedAtStartOfRequest, contextHashWhenChainProceeded);
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("SecurityContextHolder set to new context, as request processing completed"); logger.debug("SecurityContextHolder now cleared, as request processing completed");
} }
} }
} }
@ -327,9 +328,26 @@ public class HttpSessionContextIntegrationFilter implements InitializingBean, Fi
return (SecurityContext) contextFromSessionObject; return (SecurityContext) contextFromSessionObject;
} }
private void storeSecurityContextInSession(ServletRequest request, /**
* Stores the supplied security context in the session (if available) and if it has changed since it was
* set at the start of the request.
*
* @param securityContext the context object obtained from the SecurityContextHolder after the request has
* been processed by the filter chain. SecurityContextHolder.getContext() cannot be used to obtain
* the context as it has already been cleared by the time this method is called.
* @param request the request object (used to obtain the session, if one exists).
* @param httpSessionExistedAtStartOfRequest indicates whether there was a session in place before the
* filter chain executed. If this is true, and the session is found to be null, this indicates that it was
* invalidated during the request and a new session will now be created.
* @param contextHashWhenChainProceeded the hashcode of the context before the filter chain executed.
* The context will only be stored if it has a different hashcode, indicating that the context changed
* during the request.
*
*/
private void storeSecurityContextInSession(SecurityContext securityContext,
ServletRequest request,
boolean httpSessionExistedAtStartOfRequest, boolean httpSessionExistedAtStartOfRequest,
int contextWhenChainProceeded) { int contextHashWhenChainProceeded) {
HttpSession httpSession = null; HttpSession httpSession = null;
try { try {
@ -349,13 +367,12 @@ public class HttpSessionContextIntegrationFilter implements InitializingBean, Fi
if (!allowSessionCreation) { if (!allowSessionCreation) {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger logger.debug("The HttpSession is currently null, and the "
.debug("The HttpSession is currently null, and the "
+ "HttpSessionContextIntegrationFilter is prohibited from creating an HttpSession " + "HttpSessionContextIntegrationFilter is prohibited from creating an HttpSession "
+ "(because the allowSessionCreation property is false) - SecurityContext thus not " + "(because the allowSessionCreation property is false) - SecurityContext thus not "
+ "stored for next request"); + "stored for next request");
} }
} else if (!contextObject.equals(SecurityContextHolder.getContext())) { } else if (!contextObject.equals(securityContext)) {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("HttpSession being created as SecurityContextHolder contents are non-default"); logger.debug("HttpSession being created as SecurityContextHolder contents are non-default");
} }
@ -368,24 +385,20 @@ public class HttpSessionContextIntegrationFilter implements InitializingBean, Fi
} else { } else {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("HttpSession is null, but SecurityContextHolder has not changed from default: ' " logger.debug("HttpSession is null, but SecurityContextHolder has not changed from default: ' "
+ SecurityContextHolder.getContext() + securityContext
+ "'; not creating HttpSession or storing SecurityContextHolder contents"); + "'; not creating HttpSession or storing SecurityContextHolder contents");
} }
} }
} }
} }
// If HttpSession exists, store current // If HttpSession exists, store current SecurityContextHolder contents but only if
// SecurityContextHolder contents but only if // the SecurityContext has actually changed (see JIRA SEC-37)
// SecurityContext has if (httpSession != null && securityContext.hashCode() != contextHashWhenChainProceeded) {
// actually changed (see JIRA SEC-37) httpSession.setAttribute(ACEGI_SECURITY_CONTEXT_KEY, securityContext);
if ((httpSession != null)
&& (SecurityContextHolder.getContext().hashCode() != contextWhenChainProceeded)) {
httpSession.setAttribute(ACEGI_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("SecurityContext stored to HttpSession: '" + SecurityContextHolder.getContext() logger.debug("SecurityContext stored to HttpSession: '" + securityContext + "'");
+ "'");
} }
} }
} }