Browse Source

Allow filter to update multiple HttpSession attributes (useful if servlets etc expect to find an Authentication object in a given HttpSession attribute, like Jakarta Slide).

Ben Alex 21 years ago
parent
commit
4152df1225

+ 56 - 0
core/src/main/java/org/acegisecurity/ui/webapp/HttpSessionIntegrationFilter.java

@@ -18,6 +18,9 @@ package net.sf.acegisecurity.ui.webapp;
 import net.sf.acegisecurity.Authentication;
 import net.sf.acegisecurity.ui.AbstractIntegrationFilter;
 
+import java.util.Iterator;
+import java.util.List;
+
 import javax.servlet.ServletRequest;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpSession;
@@ -53,6 +56,13 @@ import javax.servlet.http.HttpSession;
  * request.
  * </p>
  * 
+ * <P>
+ * The filter can also copy the <code>Authentication</code> object to any
+ * number of additional <code>HttpSession</code> attributes. To use this
+ * capability, provide <code>String</code>s indicating the additional
+ * attribute name(s) to {@link #setAdditionalAttributes(List)}.
+ * </p>
+ * 
  * <p>
  * See {@link AbstractIntegrationFilter} for further information.
  * </p>
@@ -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!");
+                }
+            }
+        }
+    }
 }

+ 64 - 0
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"));
+    }
 }