From 4152df1225b4be3747619a8659cce084a43aca26 Mon Sep 17 00:00:00 2001
From: Ben Alex
+ * The filter can also copy the Authentication object to any
+ * number of additional HttpSession attributes. To use this
+ * capability, provide Strings indicating the additional
+ * attribute name(s) to {@link #setAdditionalAttributes(List)}.
+ *
* See {@link AbstractIntegrationFilter} for further information. *
@@ -65,8 +75,21 @@ public class HttpSessionIntegrationFilter extends AbstractIntegrationFilter { public static final String ACEGI_SECURITY_AUTHENTICATION_KEY = "ACEGI_SECURITY_AUTHENTICATION"; + //~ Instance fields ======================================================== + + private List additionalAttributes = null; + //~ Methods ================================================================ + public void setAdditionalAttributes(List additionalAttributes) { + validateList(additionalAttributes); + this.additionalAttributes = additionalAttributes; + } + + public List getAdditionalAttributes() { + return additionalAttributes; + } + public void commitToContainer(ServletRequest request, Authentication authentication) { if (request instanceof HttpServletRequest) { @@ -75,6 +98,7 @@ public class HttpSessionIntegrationFilter extends AbstractIntegrationFilter { if (httpSession != null) { httpSession.setAttribute(ACEGI_SECURITY_AUTHENTICATION_KEY, authentication); + updateOtherLocations(httpSession, authentication); } } } @@ -87,6 +111,9 @@ public class HttpSessionIntegrationFilter extends AbstractIntegrationFilter { Object authObject = httpSession.getAttribute(ACEGI_SECURITY_AUTHENTICATION_KEY); if (authObject instanceof Authentication) { + updateOtherLocations(httpSession, + (Authentication) authObject); + return authObject; } } @@ -94,4 +121,33 @@ public class HttpSessionIntegrationFilter extends AbstractIntegrationFilter { return null; } + + private void updateOtherLocations(HttpSession session, + Authentication authentication) { + if (additionalAttributes == null) { + return; + } + + Iterator iter = additionalAttributes.iterator(); + + while (iter.hasNext()) { + String attribute = (String) iter.next(); + session.setAttribute(attribute, authentication); + } + } + + private void validateList(List newAdditionalAttributes) { + if (newAdditionalAttributes != null) { + Iterator iter = newAdditionalAttributes.iterator(); + + while (iter.hasNext()) { + Object objectToTest = iter.next(); + + if (!(objectToTest instanceof String)) { + throw new IllegalArgumentException( + "List of additional attributes can only contains Strings!"); + } + } + } + } } diff --git a/core/src/test/java/org/acegisecurity/ui/webapp/HttpSessionIntegrationFilterTests.java b/core/src/test/java/org/acegisecurity/ui/webapp/HttpSessionIntegrationFilterTests.java index 825c40a1d7..c3b3a2ba91 100644 --- a/core/src/test/java/org/acegisecurity/ui/webapp/HttpSessionIntegrationFilterTests.java +++ b/core/src/test/java/org/acegisecurity/ui/webapp/HttpSessionIntegrationFilterTests.java @@ -23,6 +23,9 @@ import net.sf.acegisecurity.MockHttpServletRequest; import net.sf.acegisecurity.MockHttpSession; import net.sf.acegisecurity.adapters.PrincipalAcegiUserToken; +import java.util.List; +import java.util.Vector; + /** * Tests {@link HttpSessionIntegrationFilter}. @@ -115,6 +118,19 @@ public class HttpSessionIntegrationFilterTests extends TestCase { assertEquals(principal, result); } + public void testDetectsInvalidAdditionalAttributes() { + HttpSessionIntegrationFilter filter = new HttpSessionIntegrationFilter(); + List list = new Vector(); + list.add(new Integer(4)); + + try { + filter.setAdditionalAttributes(list); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertTrue(true); + } + } + public void testHandlesIfHttpRequestIsNullForSomeReason() { HttpSessionIntegrationFilter filter = new HttpSessionIntegrationFilter(); assertEquals(null, filter.extractFromContainer(null)); @@ -132,4 +148,52 @@ public class HttpSessionIntegrationFilterTests extends TestCase { filter.extractFromContainer( new MockHttpServletRequest(null, new MockHttpSession()))); } + + public void testSettingEmptyListForAdditionalAttributesIsAcceptable() { + HttpSessionIntegrationFilter filter = new HttpSessionIntegrationFilter(); + filter.setAdditionalAttributes(new Vector()); + assertTrue(filter.getAdditionalAttributes() != null); + } + + public void testSettingNullForAdditionalAttributesIsAcceptable() { + HttpSessionIntegrationFilter filter = new HttpSessionIntegrationFilter(); + filter.setAdditionalAttributes(null); + assertNull(filter.getAdditionalAttributes()); + } + + public void testUpdatesAdditionalAttributes() { + // Build a mock session containing the authenticated user + PrincipalAcegiUserToken principal = new PrincipalAcegiUserToken("key", + "someone", "password", + new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_ROLE")}); + MockHttpSession session = new MockHttpSession(); + session.setAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY, + principal); + + // Check our attributes are not presently set + assertNull(session.getAttribute("SOME_EXTRA_ATTRIBUTE_1")); + assertNull(session.getAttribute("SOME_EXTRA_ATTRIBUTE_2")); + + // Generate filter + HttpSessionIntegrationFilter filter = new HttpSessionIntegrationFilter(); + List list = new Vector(); + list.add("SOME_EXTRA_ATTRIBUTE_1"); + list.add("SOME_EXTRA_ATTRIBUTE_2"); + filter.setAdditionalAttributes(list); + + // Confirm filter can extract required credentials from session + Object result = filter.extractFromContainer(new MockHttpServletRequest( + null, session)); + + if (!(result instanceof PrincipalAcegiUserToken)) { + fail("Should have returned PrincipalAcegiUserToken"); + } + + PrincipalAcegiUserToken castResult = (PrincipalAcegiUserToken) result; + assertEquals(principal, result); + + // Now double-check it updated our earlier set additionalAttributes + assertEquals(principal, session.getAttribute("SOME_EXTRA_ATTRIBUTE_1")); + assertEquals(principal, session.getAttribute("SOME_EXTRA_ATTRIBUTE_2")); + } }