diff --git a/core/src/main/java/org/acegisecurity/context/HttpSessionContextIntegrationFilter.java b/core/src/main/java/org/acegisecurity/context/HttpSessionContextIntegrationFilter.java index 80b2193e31..8c2c16045f 100644 --- a/core/src/main/java/org/acegisecurity/context/HttpSessionContextIntegrationFilter.java +++ b/core/src/main/java/org/acegisecurity/context/HttpSessionContextIntegrationFilter.java @@ -32,6 +32,7 @@ import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; +import org.springframework.web.util.WebUtils; /** * Populates the {@link SecurityContextHolder} with information obtained from @@ -94,13 +95,15 @@ import org.springframework.util.ReflectionUtils; * @author Ben Alex * @author Patrick Burleson * @version $Id: HttpSessionContextIntegrationFilter.java 1784 2007-02-24 - * 21:00:24Z luke_t $ + * 21:00:24Z luke_t $ */ -public class HttpSessionContextIntegrationFilter implements InitializingBean, Filter { +public class HttpSessionContextIntegrationFilter implements InitializingBean, + Filter { // ~ Static fields/initializers // ===================================================================================== - protected static final Log logger = LogFactory.getLog(HttpSessionContextIntegrationFilter.class); + protected static final Log logger = LogFactory + .getLog(HttpSessionContextIntegrationFilter.class); static final String FILTER_APPLIED = "__acegi_session_integration_filter_applied"; @@ -172,13 +175,16 @@ public class HttpSessionContextIntegrationFilter implements InitializingBean, Fi // ======================================================================================================== public void afterPropertiesSet() throws Exception { - if ((this.context == null) || (!SecurityContext.class.isAssignableFrom(this.context))) { - throw new IllegalArgumentException("context must be defined and implement SecurityContext " - + "(typically use org.acegisecurity.context.SecurityContextImpl; existing class is " + this.context - + ")"); + if ((this.context == null) + || (!SecurityContext.class.isAssignableFrom(this.context))) { + throw new IllegalArgumentException( + "context must be defined and implement SecurityContext " + + "(typically use org.acegisecurity.context.SecurityContextImpl; existing class is " + + this.context + ")"); } - if ((forceEagerSessionCreation == true) && (allowSessionCreation == false)) { + if ((forceEagerSessionCreation == true) + && (allowSessionCreation == false)) { throw new IllegalArgumentException( "If using forceEagerSessionCreation, you must set allowSessionCreation to also be true"); } @@ -190,59 +196,60 @@ public class HttpSessionContextIntegrationFilter implements InitializingBean, Fi public void destroy() { } - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, - ServletException { + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) throws IOException, ServletException { boolean filterApplied = false; if ((request != null) && (request.getAttribute(FILTER_APPLIED) != null)) { // ensure that filter is only applied once per request + System.out.println("Filter already applied so moving on"); chain.doFilter(request, response); - } - else { - if (request != null) { - filterApplied = true; - request.setAttribute(FILTER_APPLIED, Boolean.TRUE); - } - + } else { HttpSession httpSession = null; boolean httpSessionExistedAtStartOfRequest = false; try { - httpSession = ((HttpServletRequest) request).getSession(forceEagerSessionCreation); - } - catch (IllegalStateException ignored) { + httpSession = ((HttpServletRequest) request) + .getSession(forceEagerSessionCreation); + } catch (IllegalStateException ignored) { } if (httpSession != null) { httpSessionExistedAtStartOfRequest = true; - Object contextFromSessionObject = httpSession.getAttribute(ACEGI_SECURITY_CONTEXT_KEY); + Object contextFromSessionObject = httpSession + .getAttribute(ACEGI_SECURITY_CONTEXT_KEY); if (contextFromSessionObject != null) { // Clone if required (see SEC-356) if (cloneFromHttpSession) { - Assert.isInstanceOf(Cloneable.class, contextFromSessionObject, - "Context must implement Clonable and provide a Object.clone() method"); + Assert + .isInstanceOf(Cloneable.class, + contextFromSessionObject, + "Context must implement Clonable and provide a Object.clone() method"); try { - Method m = contextFromSessionObject.getClass().getMethod("clone", new Class[] {}); + Method m = contextFromSessionObject.getClass() + .getMethod("clone", new Class[] {}); if (!m.isAccessible()) { m.setAccessible(true); } - contextFromSessionObject = m.invoke(contextFromSessionObject, new Object[] {}); - } - catch (Exception ex) { + contextFromSessionObject = m.invoke( + contextFromSessionObject, new Object[] {}); + } catch (Exception ex) { ReflectionUtils.handleReflectionException(ex); } } if (contextFromSessionObject instanceof SecurityContext) { if (logger.isDebugEnabled()) { - logger.debug("Obtained from ACEGI_SECURITY_CONTEXT a valid SecurityContext and " - + "set to SecurityContextHolder: '" + contextFromSessionObject + "'"); + logger + .debug("Obtained from ACEGI_SECURITY_CONTEXT a valid SecurityContext and " + + "set to SecurityContextHolder: '" + + contextFromSessionObject + "'"); } - SecurityContextHolder.setContext((SecurityContext) contextFromSessionObject); - } - else { + SecurityContextHolder + .setContext((SecurityContext) contextFromSessionObject); + } else { if (logger.isWarnEnabled()) { logger .warn("ACEGI_SECURITY_CONTEXT did not contain a SecurityContext but contained: '" @@ -255,60 +262,66 @@ public class HttpSessionContextIntegrationFilter implements InitializingBean, Fi SecurityContextHolder.setContext(generateNewContext()); } - } - else { + } else { if (logger.isDebugEnabled()) { - logger.debug("HttpSession returned null object for ACEGI_SECURITY_CONTEXT - new " - + "SecurityContext instance associated with SecurityContextHolder"); + logger + .debug("HttpSession returned null object for ACEGI_SECURITY_CONTEXT - new " + + "SecurityContext instance associated with SecurityContextHolder"); } SecurityContextHolder.setContext(generateNewContext()); } - } - else { + + } else { if (logger.isDebugEnabled()) { - logger.debug("No HttpSession currently exists - new SecurityContext instance " - + "associated with SecurityContextHolder"); + logger + .debug("No HttpSession currently exists - new SecurityContext instance " + + "associated with SecurityContextHolder"); } SecurityContextHolder.setContext(generateNewContext()); } + // end synch + // Make the HttpSession null, as we want to ensure we don't keep // a reference to the HttpSession laying around in case the // chain.doFilter() invalidates it. httpSession = null; // Proceed with chain - int contextWhenChainProceeded = SecurityContextHolder.getContext().hashCode(); + int contextWhenChainProceeded = SecurityContextHolder.getContext() + .hashCode(); try { + filterApplied = true; + request.setAttribute(FILTER_APPLIED, Boolean.TRUE); chain.doFilter(request, response); - } - catch (IOException ioe) { + } catch (IOException ioe) { throw ioe; - } - catch (ServletException se) { + } catch (ServletException se) { + throw se; - } - finally { + } finally { // do clean up, even if there was an exception // Store context back to HttpSession try { - httpSession = ((HttpServletRequest) request).getSession(false); - } - catch (IllegalStateException ignored) { + httpSession = ((HttpServletRequest) request) + .getSession(false); + } catch (IllegalStateException ignored) { } if ((httpSession == null) && httpSessionExistedAtStartOfRequest) { if (logger.isDebugEnabled()) { - logger.debug("HttpSession is now null, but was not null at start of request; " - + "session was invalidated, so do not create a new session"); + logger + .debug("HttpSession is now null, but was not null at start of request; " + + "session was invalidated, so do not create a new session"); } } // Generate a HttpSession only if we need to - if ((httpSession == null) && !httpSessionExistedAtStartOfRequest) { + if ((httpSession == null) + && !httpSessionExistedAtStartOfRequest) { if (!allowSessionCreation) { if (logger.isDebugEnabled()) { logger @@ -317,23 +330,24 @@ public class HttpSessionContextIntegrationFilter implements InitializingBean, Fi + "(because the allowSessionCreation property is false) - SecurityContext thus not " + "stored for next request"); } - } - else if (!contextObject.equals(SecurityContextHolder.getContext())) { + } else if (!contextObject.equals(SecurityContextHolder + .getContext())) { 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"); } try { - httpSession = ((HttpServletRequest) request).getSession(true); + httpSession = ((HttpServletRequest) request) + .getSession(true); + } catch (IllegalStateException ignored) { } - catch (IllegalStateException ignored) { - } - } - else { + } else { if (logger.isDebugEnabled()) { logger .debug("HttpSession is null, but SecurityContextHolder has not changed from default: ' " - + SecurityContextHolder.getContext() + + SecurityContextHolder + .getContext() + "'; not creating HttpSession or storing SecurityContextHolder contents"); } } @@ -345,36 +359,39 @@ public class HttpSessionContextIntegrationFilter implements InitializingBean, Fi // actually changed (see JIRA SEC-37) if ((httpSession != null) && (SecurityContextHolder.getContext().hashCode() != contextWhenChainProceeded)) { - httpSession.setAttribute(ACEGI_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext()); + httpSession.setAttribute(ACEGI_SECURITY_CONTEXT_KEY, + SecurityContextHolder.getContext()); if (logger.isDebugEnabled()) { - logger.debug("SecurityContext stored to HttpSession: '" + SecurityContextHolder.getContext() - + "'"); + logger.debug("SecurityContext stored to HttpSession: '" + + SecurityContextHolder.getContext() + "'"); } } if (filterApplied) { request.removeAttribute(FILTER_APPLIED); } - + // Remove SecurityContextHolder contents SecurityContextHolder.clearContext(); if (logger.isDebugEnabled()) { - logger.debug("SecurityContextHolder set to new context, as request processing completed"); + logger + .debug("SecurityContextHolder set to new context, as request processing completed"); } + } + } + } public SecurityContext generateNewContext() throws ServletException { try { return (SecurityContext) this.context.newInstance(); - } - catch (InstantiationException ie) { + } catch (InstantiationException ie) { throw new ServletException(ie); - } - catch (IllegalAccessException iae) { + } catch (IllegalAccessException iae) { throw new ServletException(iae); } } @@ -386,9 +403,11 @@ public class HttpSessionContextIntegrationFilter implements InitializingBean, Fi /** * Does nothing. We use IoC container lifecycle services instead. * - * @param filterConfig ignored + * @param filterConfig + * ignored * - * @throws ServletException ignored + * @throws ServletException + * ignored */ public void init(FilterConfig filterConfig) throws ServletException { } diff --git a/core/src/test/java/org/acegisecurity/context/HttpSessionContextIntegrationFilterTests.java b/core/src/test/java/org/acegisecurity/context/HttpSessionContextIntegrationFilterTests.java index 11ac1a6139..355842a4a8 100644 --- a/core/src/test/java/org/acegisecurity/context/HttpSessionContextIntegrationFilterTests.java +++ b/core/src/test/java/org/acegisecurity/context/HttpSessionContextIntegrationFilterTests.java @@ -23,6 +23,7 @@ import org.acegisecurity.GrantedAuthorityImpl; import org.acegisecurity.MockFilterConfig; import org.acegisecurity.adapters.PrincipalAcegiUserToken; +import org.jmock.Mock; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; @@ -36,271 +37,387 @@ import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; - /** * Tests {@link HttpSessionContextIntegrationFilter}. - * + * * @author Ben Alex - * @version $Id$ + * @version $Id: HttpSessionContextIntegrationFilterTests.java 1858 2007-05-24 + * 02:04:47Z benalex $ */ public class HttpSessionContextIntegrationFilterTests extends TestCase { - //~ Constructors =================================================================================================== + // ~ Constructors + // =================================================================================================== - public HttpSessionContextIntegrationFilterTests() { - super(); - } + public HttpSessionContextIntegrationFilterTests() { + super(); + } - public HttpSessionContextIntegrationFilterTests(String arg0) { - super(arg0); - } + public HttpSessionContextIntegrationFilterTests(String arg0) { + super(arg0); + } - //~ Methods ======================================================================================================== + // ~ Methods + // ======================================================================================================== - private void executeFilterInContainerSimulator(FilterConfig filterConfig, Filter filter, ServletRequest request, - ServletResponse response, FilterChain filterChain) - throws ServletException, IOException { - filter.init(filterConfig); - filter.doFilter(request, response, filterChain); - filter.destroy(); - } + private static void executeFilterInContainerSimulator( + FilterConfig filterConfig, Filter filter, ServletRequest request, + ServletResponse response, FilterChain filterChain) + throws ServletException, IOException { + filter.init(filterConfig); + filter.doFilter(request, response, filterChain); + filter.destroy(); + } - public static void main(String[] args) { - junit.textui.TestRunner.run(HttpSessionContextIntegrationFilterTests.class); - } + public static void main(String[] args) { + junit.textui.TestRunner + .run(HttpSessionContextIntegrationFilterTests.class); + } - public void testDetectsIncompatibleSessionProperties() - throws Exception { - HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter(); + public void testDetectsIncompatibleSessionProperties() throws Exception { + HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter(); - try { - filter.setAllowSessionCreation(false); - filter.setForceEagerSessionCreation(true); - filter.afterPropertiesSet(); - fail("Shown have thrown IllegalArgumentException"); - } catch (IllegalArgumentException expected) { - assertTrue(true); - } + try { + filter.setAllowSessionCreation(false); + filter.setForceEagerSessionCreation(true); + filter.afterPropertiesSet(); + fail("Shown have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertTrue(true); + } - filter.setAllowSessionCreation(true); - filter.afterPropertiesSet(); - assertTrue(true); - } + filter.setAllowSessionCreation(true); + filter.afterPropertiesSet(); + assertTrue(true); + } - public void testDetectsMissingOrInvalidContext() throws Exception { - HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter(); + public void testDetectsMissingOrInvalidContext() throws Exception { + HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter(); - try { - filter.setContext(null); - filter.afterPropertiesSet(); - fail("Shown have thrown IllegalArgumentException"); - } catch (IllegalArgumentException expected) { - assertTrue(true); - } + try { + filter.setContext(null); + filter.afterPropertiesSet(); + fail("Shown have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertTrue(true); + } - try { - filter.setContext(Integer.class); - assertEquals(Integer.class, filter.getContext()); - filter.afterPropertiesSet(); - fail("Shown have thrown IllegalArgumentException"); - } catch (IllegalArgumentException expected) { - assertTrue(true); - } - } + try { + filter.setContext(Integer.class); + assertEquals(Integer.class, filter.getContext()); + filter.afterPropertiesSet(); + fail("Shown have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertTrue(true); + } + } - public void testExceptionWithinFilterChainStillClearsSecurityContextHolder() - throws Exception { - // Build an Authentication object we simulate came from HttpSession - PrincipalAcegiUserToken sessionPrincipal = new PrincipalAcegiUserToken("key", "someone", "password", - new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_ROLE")}, null); + public void testExceptionWithinFilterChainStillClearsSecurityContextHolder() + throws Exception { + // Build an Authentication object we simulate came from HttpSession + PrincipalAcegiUserToken sessionPrincipal = new PrincipalAcegiUserToken( + "key", + "someone", + "password", + new GrantedAuthority[] { new GrantedAuthorityImpl("SOME_ROLE") }, + null); - // Build a Context to store in HttpSession (simulating prior request) - SecurityContext sc = new SecurityContextImpl(); - sc.setAuthentication(sessionPrincipal); + // Build a Context to store in HttpSession (simulating prior request) + SecurityContext sc = new SecurityContextImpl(); + sc.setAuthentication(sessionPrincipal); - // Build a mock request - MockHttpServletRequest request = new MockHttpServletRequest(); - request.getSession().setAttribute(HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY, sc); + // Build a mock request + MockHttpServletRequest request = new MockHttpServletRequest(); + request.getSession().setAttribute( + HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY, + sc); - MockHttpServletResponse response = new MockHttpServletResponse(); - FilterChain chain = new MockFilterChain(sessionPrincipal, null, new IOException()); + MockHttpServletResponse response = new MockHttpServletResponse(); + FilterChain chain = new MockFilterChain(sessionPrincipal, null, + new IOException()); - // Prepare filter - HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter(); - filter.setContext(SecurityContextImpl.class); - filter.afterPropertiesSet(); + // Prepare filter + HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter(); + filter.setContext(SecurityContextImpl.class); + filter.afterPropertiesSet(); - // Execute filter - try { - executeFilterInContainerSimulator(new MockFilterConfig(), filter, request, response, chain); - fail("We should have received the IOException thrown inside the filter chain here"); - } catch (IOException ioe) { - assertTrue(true); - } + // Execute filter + try { + executeFilterInContainerSimulator(new MockFilterConfig(), filter, + request, response, chain); + fail("We should have received the IOException thrown inside the filter chain here"); + } catch (IOException ioe) { + assertTrue(true); + } - // Check the SecurityContextHolder is null, even though an exception was thrown during chain - assertEquals(new SecurityContextImpl(), SecurityContextHolder.getContext()); - assertNull("Should have cleared FILTER_APPLIED", request.getAttribute(HttpSessionContextIntegrationFilter.FILTER_APPLIED)); - } + // Check the SecurityContextHolder is null, even though an exception was + // thrown during chain + assertEquals(new SecurityContextImpl(), SecurityContextHolder + .getContext()); + assertNull( + "Should have cleared FILTER_APPLIED", + request + .getAttribute(HttpSessionContextIntegrationFilter.FILTER_APPLIED)); + } - public void testExistingContextContentsCopiedIntoContextHolderFromSessionAndChangesToContextCopiedBackToSession() - throws Exception { - // Build an Authentication object we simulate came from HttpSession - PrincipalAcegiUserToken sessionPrincipal = new PrincipalAcegiUserToken("key", "someone", "password", - new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_ROLE")}, null); + public void testExistingContextContentsCopiedIntoContextHolderFromSessionAndChangesToContextCopiedBackToSession() + throws Exception { + // Build an Authentication object we simulate came from HttpSession + PrincipalAcegiUserToken sessionPrincipal = new PrincipalAcegiUserToken( + "key", + "someone", + "password", + new GrantedAuthority[] { new GrantedAuthorityImpl("SOME_ROLE") }, + null); - // Build an Authentication object we simulate our Authentication changed it to - PrincipalAcegiUserToken updatedPrincipal = new PrincipalAcegiUserToken("key", "someone", "password", - new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_DIFFERENT_ROLE")}, null); + // Build an Authentication object we simulate our Authentication changed + // it to + PrincipalAcegiUserToken updatedPrincipal = new PrincipalAcegiUserToken( + "key", "someone", "password", + new GrantedAuthority[] { new GrantedAuthorityImpl( + "SOME_DIFFERENT_ROLE") }, null); - // Build a Context to store in HttpSession (simulating prior request) - SecurityContext sc = new SecurityContextImpl(); - sc.setAuthentication(sessionPrincipal); + // Build a Context to store in HttpSession (simulating prior request) + SecurityContext sc = new SecurityContextImpl(); + sc.setAuthentication(sessionPrincipal); - // Build a mock request - MockHttpServletRequest request = new MockHttpServletRequest(); - request.getSession().setAttribute(HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY, sc); + // Build a mock request + MockHttpServletRequest request = new MockHttpServletRequest(); + request.getSession().setAttribute( + HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY, + sc); - MockHttpServletResponse response = new MockHttpServletResponse(); - FilterChain chain = new MockFilterChain(sessionPrincipal, updatedPrincipal, null); + MockHttpServletResponse response = new MockHttpServletResponse(); + FilterChain chain = new MockFilterChain(sessionPrincipal, + updatedPrincipal, null); - // Prepare filter - HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter(); - filter.setContext(SecurityContextImpl.class); - filter.afterPropertiesSet(); + // Prepare filter + HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter(); + filter.setContext(SecurityContextImpl.class); + filter.afterPropertiesSet(); - // Execute filter - executeFilterInContainerSimulator(new MockFilterConfig(), filter, request, response, chain); + // Execute filter + executeFilterInContainerSimulator(new MockFilterConfig(), filter, + request, response, chain); - // Obtain new/update Authentication from HttpSession - SecurityContext context = (SecurityContext) request.getSession() - .getAttribute(HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY); - assertEquals(updatedPrincipal, ((SecurityContext) context).getAuthentication()); - } + // Obtain new/update Authentication from HttpSession + SecurityContext context = (SecurityContext) request + .getSession() + .getAttribute( + HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY); + assertEquals(updatedPrincipal, ((SecurityContext) context) + .getAuthentication()); + } - public void testHttpSessionCreatedWhenContextHolderChanges() - throws Exception { - // Build an Authentication object we simulate our Authentication changed it to - PrincipalAcegiUserToken updatedPrincipal = new PrincipalAcegiUserToken("key", "someone", "password", - new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_DIFFERENT_ROLE")}, null); + public void testHttpSessionCreatedWhenContextHolderChanges() + throws Exception { + // Build an Authentication object we simulate our Authentication changed + // it to + PrincipalAcegiUserToken updatedPrincipal = new PrincipalAcegiUserToken( + "key", "someone", "password", + new GrantedAuthority[] { new GrantedAuthorityImpl( + "SOME_DIFFERENT_ROLE") }, null); - // Build a mock request - MockHttpServletRequest request = new MockHttpServletRequest(); - MockHttpServletResponse response = new MockHttpServletResponse(); - FilterChain chain = new MockFilterChain(null, updatedPrincipal, null); + // Build a mock request + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + FilterChain chain = new MockFilterChain(null, updatedPrincipal, null); - // Prepare filter - HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter(); - filter.setContext(SecurityContextImpl.class); - // don't call afterPropertiesSet to test case when not instantiated by Spring - //filter.afterPropertiesSet(); + // Prepare filter + HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter(); + filter.setContext(SecurityContextImpl.class); + // don't call afterPropertiesSet to test case when not instantiated by + // Spring + // filter.afterPropertiesSet(); - // Execute filter - executeFilterInContainerSimulator(new MockFilterConfig(), filter, request, response, chain); + // Execute filter + executeFilterInContainerSimulator(new MockFilterConfig(), filter, + request, response, chain); - // Obtain new/updated Authentication from HttpSession - SecurityContext context = (SecurityContext) request.getSession(false) - .getAttribute(HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY); - assertEquals(updatedPrincipal, ((SecurityContext) context).getAuthentication()); - } + // Obtain new/updated Authentication from HttpSession + SecurityContext context = (SecurityContext) request + .getSession(false) + .getAttribute( + HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY); + assertEquals(updatedPrincipal, ((SecurityContext) context) + .getAuthentication()); + } - public void testHttpSessionEagerlyCreatedWhenDirected() - throws Exception { - // Build a mock request - MockHttpServletRequest request = new MockHttpServletRequest(null, null); - MockHttpServletResponse response = new MockHttpServletResponse(); - FilterChain chain = new MockFilterChain(null, null, null); + public void testHttpSessionEagerlyCreatedWhenDirected() throws Exception { + // Build a mock request + MockHttpServletRequest request = new MockHttpServletRequest(null, null); + MockHttpServletResponse response = new MockHttpServletResponse(); + FilterChain chain = new MockFilterChain(null, null, null); - // Prepare filter - HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter(); - filter.setContext(SecurityContextImpl.class); - filter.setForceEagerSessionCreation(true); // non-default - filter.afterPropertiesSet(); + // Prepare filter + HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter(); + filter.setContext(SecurityContextImpl.class); + filter.setForceEagerSessionCreation(true); // non-default + filter.afterPropertiesSet(); - // Execute filter - executeFilterInContainerSimulator(new MockFilterConfig(), filter, request, response, chain); + // Execute filter + executeFilterInContainerSimulator(new MockFilterConfig(), filter, + request, response, chain); - // Check the session is not null - assertNotNull(request.getSession(false)); - } + // Check the session is not null + assertNotNull(request.getSession(false)); + } - public void testHttpSessionNotCreatedUnlessContextHolderChanges() - throws Exception { - // Build a mock request - MockHttpServletRequest request = new MockHttpServletRequest(null, null); - MockHttpServletResponse response = new MockHttpServletResponse(); - FilterChain chain = new MockFilterChain(null, null, null); + public void testHttpSessionNotCreatedUnlessContextHolderChanges() + throws Exception { + // Build a mock request + MockHttpServletRequest request = new MockHttpServletRequest(null, null); + MockHttpServletResponse response = new MockHttpServletResponse(); + FilterChain chain = new MockFilterChain(null, null, null); - // Prepare filter - HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter(); - filter.setContext(SecurityContextImpl.class); - filter.afterPropertiesSet(); + // Prepare filter + HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter(); + filter.setContext(SecurityContextImpl.class); + filter.afterPropertiesSet(); - // Execute filter - executeFilterInContainerSimulator(new MockFilterConfig(), filter, request, response, chain); + // Execute filter + executeFilterInContainerSimulator(new MockFilterConfig(), filter, + request, response, chain); - // Check the session is null - assertNull(request.getSession(false)); - } + // Check the session is null + assertNull(request.getSession(false)); + } - public void testHttpSessionWithNonContextInWellKnownLocationIsOverwritten() - throws Exception { - // Build an Authentication object we simulate our Authentication changed it to - PrincipalAcegiUserToken updatedPrincipal = new PrincipalAcegiUserToken("key", "someone", "password", - new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_DIFFERENT_ROLE")}, null); + public void testHttpSessionWithNonContextInWellKnownLocationIsOverwritten() + throws Exception { + // Build an Authentication object we simulate our Authentication changed + // it to + PrincipalAcegiUserToken updatedPrincipal = new PrincipalAcegiUserToken( + "key", "someone", "password", + new GrantedAuthority[] { new GrantedAuthorityImpl( + "SOME_DIFFERENT_ROLE") }, null); - // Build a mock request - MockHttpServletRequest request = new MockHttpServletRequest(); - request.getSession() - .setAttribute(HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY, "NOT_A_CONTEXT_OBJECT"); + // Build a mock request + MockHttpServletRequest request = new MockHttpServletRequest(); + request.getSession().setAttribute( + HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY, + "NOT_A_CONTEXT_OBJECT"); - MockHttpServletResponse response = new MockHttpServletResponse(); - FilterChain chain = new MockFilterChain(null, updatedPrincipal, null); + MockHttpServletResponse response = new MockHttpServletResponse(); + FilterChain chain = new MockFilterChain(null, updatedPrincipal, null); - // Prepare filter - HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter(); - filter.setContext(SecurityContextImpl.class); - filter.afterPropertiesSet(); + // Prepare filter + HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter(); + filter.setContext(SecurityContextImpl.class); + filter.afterPropertiesSet(); - // Execute filter - executeFilterInContainerSimulator(new MockFilterConfig(), filter, request, response, chain); + // Execute filter + executeFilterInContainerSimulator(new MockFilterConfig(), filter, + request, response, chain); - // Obtain new/update Authentication from HttpSession - SecurityContext context = (SecurityContext) request.getSession() - .getAttribute(HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY); - assertEquals(updatedPrincipal, ((SecurityContext) context).getAuthentication()); - } + // Obtain new/update Authentication from HttpSession + SecurityContext context = (SecurityContext) request + .getSession() + .getAttribute( + HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY); + assertEquals(updatedPrincipal, ((SecurityContext) context) + .getAuthentication()); + } - //~ Inner Classes ================================================================================================== + public void testConcurrentThreadsLazilyChangeFilterAppliedValueToTrue() + throws Exception { + PrincipalAcegiUserToken sessionPrincipal = new PrincipalAcegiUserToken( + "key", + "someone", + "password", + new GrantedAuthority[] { new GrantedAuthorityImpl("SOME_ROLE") }, + null); - private class MockFilterChain extends TestCase implements FilterChain { - private Authentication changeContextHolder; - private Authentication expectedOnContextHolder; - private IOException toThrowDuringChain; + // Build a Context to store in HttpSession (simulating prior request) + SecurityContext sc = new SecurityContextImpl(); + sc.setAuthentication(sessionPrincipal); - public MockFilterChain(Authentication expectedOnContextHolder, Authentication changeContextHolder, - IOException toThrowDuringChain) { - this.expectedOnContextHolder = expectedOnContextHolder; - this.changeContextHolder = changeContextHolder; - this.toThrowDuringChain = toThrowDuringChain; - } + MockHttpServletRequest request = new MockHttpServletRequest(); + request.getSession().setAttribute( + HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY, + sc); + MockHttpServletResponse response = new MockHttpServletResponse(); - private MockFilterChain() {} + // Prepare filter + HttpSessionContextIntegrationFilter filter = new HttpSessionContextIntegrationFilter(); + filter.setContext(SecurityContextImpl.class); + filter.afterPropertiesSet(); - public void doFilter(ServletRequest arg0, ServletResponse arg1) - throws IOException, ServletException { - if (expectedOnContextHolder != null) { - assertEquals(expectedOnContextHolder, SecurityContextHolder.getContext().getAuthentication()); - } + for (int i = 0; i < 3; i++) { + ThreadRunner runner = new ThreadRunner(request, response, filter, + new MockFilterChain(sessionPrincipal, null, null)); + runner.start(); + } - if (changeContextHolder != null) { - SecurityContext sc = SecurityContextHolder.getContext(); - sc.setAuthentication(changeContextHolder); - SecurityContextHolder.setContext(sc); - } + } - if (toThrowDuringChain != null) { - throw toThrowDuringChain; - } - } - } + // ~ Inner Classes + // ================================================================================================== + + private class MockFilterChain extends TestCase implements FilterChain { + private Authentication changeContextHolder; + private Authentication expectedOnContextHolder; + private IOException toThrowDuringChain; + + public MockFilterChain(Authentication expectedOnContextHolder, + Authentication changeContextHolder, + IOException toThrowDuringChain) { + this.expectedOnContextHolder = expectedOnContextHolder; + this.changeContextHolder = changeContextHolder; + this.toThrowDuringChain = toThrowDuringChain; + } + + private MockFilterChain() { + } + + public void doFilter(ServletRequest arg0, ServletResponse arg1) + throws IOException, ServletException { + + if (expectedOnContextHolder != null) { + assertEquals(expectedOnContextHolder, SecurityContextHolder + .getContext().getAuthentication()); + } + + if (changeContextHolder != null) { + SecurityContext sc = SecurityContextHolder.getContext(); + sc.setAuthentication(changeContextHolder); + SecurityContextHolder.setContext(sc); + } + + if (toThrowDuringChain != null) { + throw toThrowDuringChain; + } + + } + } + + private static class ThreadRunner extends Thread { + private MockHttpServletRequest request; + private MockHttpServletResponse response; + private HttpSessionContextIntegrationFilter filter; + private MockFilterChain chain; + + public ThreadRunner(MockHttpServletRequest request, + MockHttpServletResponse response, + HttpSessionContextIntegrationFilter filter, + MockFilterChain chain) { + this.request = request; + this.response = response; + this.filter = filter; + this.chain = chain; + } + + public void run() { + try { + // Execute filter + executeFilterInContainerSimulator(new MockFilterConfig(), + filter, request, response, chain); + + // Check the session is not null + assertNotNull(request.getSession(false)); + } catch (Exception e) { + e.printStackTrace(); + } + } + + } }