Przeglądaj źródła

Fixed issue with caching by making AbstractIntegrationFilter (and its subclasses) write the new Authentication object to the well-known location.

Ben Alex 21 lat temu
rodzic
commit
eaa92cd80a

+ 9 - 0
adapters/jboss/src/main/java/org/acegisecurity/adapters/jboss/JbossIntegrationFilter.java

@@ -45,6 +45,15 @@ import javax.servlet.ServletRequest;
 public class JbossIntegrationFilter extends AbstractIntegrationFilter {
     //~ Methods ================================================================
 
+    /**
+     * Not supported for this type of well-known location.
+     *
+     * @param request DOCUMENT ME!
+     * @param authentication DOCUMENT ME!
+     */
+    public void commitToContainer(ServletRequest request,
+        Authentication authentication) {}
+
     public Object extractFromContainer(ServletRequest request) {
         Subject subject = null;
 

+ 3 - 0
adapters/jboss/src/test/java/org/acegisecurity/adapters/jboss/JbossIntegrationFilterTests.java

@@ -77,6 +77,9 @@ public class JbossIntegrationFilterTests extends TestCase {
 
         PrincipalAcegiUserToken castResult = (PrincipalAcegiUserToken) result;
         assertEquals(principal, result);
+
+        filter.commitToContainer(new MockHttpServletRequest(principal, null),
+            principal);
     }
 
     public void testReturnsNullIfContextReturnsSomethingOtherThanASubject() {

+ 6 - 0
changelog.txt

@@ -1,3 +1,9 @@
+Changes in version 0.x (2004-xx-xx)
+-----------------------------------
+
+* Added samples/quick-start
+* Fixed issue with caching of Authentication objects
+
 Changes in version 0.5 (2004-04-29)
 -----------------------------------
 

+ 10 - 0
core/src/main/java/org/acegisecurity/adapters/HttpRequestIntegrationFilter.java

@@ -15,6 +15,7 @@
 
 package net.sf.acegisecurity.adapters;
 
+import net.sf.acegisecurity.Authentication;
 import net.sf.acegisecurity.ui.AbstractIntegrationFilter;
 
 import org.apache.commons.logging.Log;
@@ -42,6 +43,15 @@ public class HttpRequestIntegrationFilter extends AbstractIntegrationFilter {
 
     //~ Methods ================================================================
 
+    /**
+     * Not supported for this type of well-known location.
+     *
+     * @param request DOCUMENT ME!
+     * @param authentication DOCUMENT ME!
+     */
+    public void commitToContainer(ServletRequest request,
+        Authentication authentication) {}
+
     public Object extractFromContainer(ServletRequest request) {
         if (request instanceof HttpServletRequest) {
             return ((HttpServletRequest) request).getUserPrincipal();

+ 19 - 2
core/src/main/java/org/acegisecurity/ui/AbstractIntegrationFilter.java

@@ -70,6 +70,17 @@ public abstract class AbstractIntegrationFilter implements Filter {
 
     //~ Methods ================================================================
 
+    /**
+     * Writes a new <code>Authentication</code> object to the container's
+     * well-known location, if supported the subclass.
+     *
+     * @param request which may be required by the implementing method to
+     *        access the well-known location for the current principal
+     * @param authentication the new object to be written to the container
+     */
+    public abstract void commitToContainer(ServletRequest request,
+        Authentication authentication);
+
     public void destroy() {}
 
     public void doFilter(ServletRequest request, ServletResponse response,
@@ -112,12 +123,18 @@ public abstract class AbstractIntegrationFilter implements Filter {
         if ((ContextHolder.getContext() != null)
             && ContextHolder.getContext() instanceof SecureContext) {
             if (logger.isDebugEnabled()) {
-                logger.debug("Removing Authentication from ContextHolder");
+                logger.debug(
+                    "Updating container with new Authentication object, and then removing Authentication from ContextHolder");
             }
 
-            // Get context holder and remove authentication information
+            // Get context holder
             SecureContext secureContext = (SecureContext) ContextHolder
                 .getContext();
+
+            // Update container with new Authentication object (may have been updated during method invocation)
+            this.commitToContainer(request, secureContext.getAuthentication());
+
+            // Remove authentication information from ContextHolder
             secureContext.setAuthentication(null);
             ContextHolder.setContext((Context) secureContext);
         } else {

+ 17 - 0
core/src/main/java/org/acegisecurity/ui/AutoIntegrationFilter.java

@@ -57,6 +57,23 @@ import javax.servlet.http.HttpServletRequest;
 public class AutoIntegrationFilter extends AbstractIntegrationFilter {
     //~ Methods ================================================================
 
+    public void commitToContainer(ServletRequest request,
+        Authentication authentication) {
+        if (request instanceof HttpServletRequest) {
+            HttpServletRequest httpRequest = (HttpServletRequest) request;
+
+            if (getHttpSessionIntegrationFilter().extractFromContainer(request) != null) {
+                getHttpSessionIntegrationFilter().commitToContainer(request,
+                    authentication);
+
+                return;
+            }
+
+            // Do not try JbossIntegrationFilter, as commit is unsupported.
+            // Do not try HttpRequestIntegrationFilter, as commit is unsupported.
+        }
+    }
+
     public Object extractFromContainer(ServletRequest request) {
         if (request instanceof HttpServletRequest) {
             HttpServletRequest httpRequest = (HttpServletRequest) request;

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

@@ -67,6 +67,18 @@ public class HttpSessionIntegrationFilter extends AbstractIntegrationFilter {
 
     //~ Methods ================================================================
 
+    public void commitToContainer(ServletRequest request,
+        Authentication authentication) {
+        if (request instanceof HttpServletRequest) {
+            HttpSession httpSession = ((HttpServletRequest) request).getSession();
+
+            if (httpSession != null) {
+                httpSession.setAttribute(ACEGI_SECURITY_AUTHENTICATION_KEY,
+                    authentication);
+            }
+        }
+    }
+
     public Object extractFromContainer(ServletRequest request) {
         if (request instanceof HttpServletRequest) {
             HttpSession httpSession = ((HttpServletRequest) request).getSession();

+ 3 - 0
core/src/test/java/org/acegisecurity/adapters/HttpRequestIntegrationFilterTests.java

@@ -63,6 +63,9 @@ public class HttpRequestIntegrationFilterTests extends TestCase {
 
         PrincipalAcegiUserToken castResult = (PrincipalAcegiUserToken) result;
         assertEquals(principal, result);
+
+        filter.commitToContainer(new MockHttpServletRequest(principal, null),
+            principal);
     }
 
     public void testHandlesIfHttpRequestIsNullForSomeReason() {

+ 5 - 0
core/src/test/java/org/acegisecurity/ui/AbstractIntegrationFilterTests.java

@@ -202,6 +202,11 @@ public class AbstractIntegrationFilterTests extends TestCase {
             super();
         }
 
+        public void commitToContainer(ServletRequest request,
+            Authentication authentication) {
+            this.extractFromContainerResult = authentication;
+        }
+
         public Object extractFromContainer(ServletRequest request) {
             return this.extractFromContainerResult;
         }

+ 30 - 0
core/src/test/java/org/acegisecurity/ui/AutoIntegrationFilterTests.java

@@ -17,6 +17,7 @@ package net.sf.acegisecurity.ui;
 
 import junit.framework.TestCase;
 
+import net.sf.acegisecurity.Authentication;
 import net.sf.acegisecurity.GrantedAuthority;
 import net.sf.acegisecurity.GrantedAuthorityImpl;
 import net.sf.acegisecurity.MockHttpServletRequest;
@@ -68,6 +69,30 @@ public class AutoIntegrationFilterTests extends TestCase {
         junit.textui.TestRunner.run(AutoIntegrationFilterTests.class);
     }
 
+    public void testCommitForHttpSession() {
+        // This is the object we want to commit
+        PrincipalAcegiUserToken principal = new PrincipalAcegiUserToken("key",
+                "someone", "password",
+                new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_ROLE")});
+
+        // Setup the mock so AutoIntegrationFilter detects HttpSessionIntegrationFilter should be used
+        MockHttpSessionIntegrationFilter mockHttpSessionIntegrationFilter = new MockHttpSessionIntegrationFilter(new PrincipalAcegiUserToken(
+                    "x", "x", "x",
+                    new GrantedAuthority[] {new GrantedAuthorityImpl("x")}));
+
+        // Setup the AutoIntegrationFilter to use our mock HttpSessionIntegrationFilter object
+        AutoIntegrationFilter filter = new MockAutoIntegrationFilterHttpSession(mockHttpSessionIntegrationFilter);
+
+        // Test we can commit the new object (this will override the principal with "x" in its properties)
+        filter.commitToContainer(new MockHttpServletRequest("ignored"),
+            principal);
+
+        // Test the object was indeed committed and overwrote the principal with "x" in its properties
+        assertEquals(principal,
+            mockHttpSessionIntegrationFilter.extractFromContainer(
+                new MockHttpServletRequest("ignored")));
+    }
+
     public void testDetectsAuthenticationObjectInHttpRequest() {
         AutoIntegrationFilter filter = new AutoIntegrationFilter();
         PrincipalAcegiUserToken principal = new PrincipalAcegiUserToken("key",
@@ -201,6 +226,11 @@ public class AutoIntegrationFilterTests extends TestCase {
             super();
         }
 
+        public void commitToContainer(ServletRequest request,
+            Authentication authentication) {
+            this.toReturn = authentication;
+        }
+
         public Object extractFromContainer(ServletRequest request) {
             return this.toReturn;
         }

+ 42 - 0
core/src/test/java/org/acegisecurity/ui/webapp/HttpSessionIntegrationFilterTests.java

@@ -51,6 +51,48 @@ public class HttpSessionIntegrationFilterTests extends TestCase {
         junit.textui.TestRunner.run(HttpSessionIntegrationFilterTests.class);
     }
 
+    public void testCommitFailSilentlyIfNullsProvided() {
+        HttpSessionIntegrationFilter filter = new HttpSessionIntegrationFilter();
+        filter.commitToContainer(null, null);
+        assertTrue(true);
+    }
+
+    public void testCommitOperation() {
+        // Build an Authentication object we want returned
+        PrincipalAcegiUserToken principal = new PrincipalAcegiUserToken("key",
+                "someone", "password",
+                new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_ROLE")});
+
+        // Build a mock request
+        MockHttpSession session = new MockHttpSession();
+        MockHttpServletRequest request = new MockHttpServletRequest(null,
+                session);
+
+        // Try to commit
+        HttpSessionIntegrationFilter filter = new HttpSessionIntegrationFilter();
+        filter.commitToContainer(request, principal);
+
+        // Check it committed the object
+        Object result = session.getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY);
+        assertEquals(principal, result);
+    }
+
+    public void testCommitOperationGracefullyIgnoredIfSessionIsNull() {
+        PrincipalAcegiUserToken principal = new PrincipalAcegiUserToken("key",
+                "someone", "password",
+                new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_ROLE")});
+
+        // Build a mock request
+        MockHttpSession session = null;
+        MockHttpServletRequest request = new MockHttpServletRequest(null,
+                session);
+
+        HttpSessionIntegrationFilter filter = new HttpSessionIntegrationFilter();
+        filter.commitToContainer(request, principal);
+
+        assertTrue(true);
+    }
+
     public void testCorrectOperation() {
         // Build a mock session containing the authenticated user
         PrincipalAcegiUserToken principal = new PrincipalAcegiUserToken("key",