瀏覽代碼

Add InteractiveAuthenticationSuccessEvent handling to authentication mechanisms.

Ben Alex 20 年之前
父節點
當前提交
5c883e639f

+ 39 - 17
core/src/main/java/org/acegisecurity/ui/AbstractProcessingFilter.java

@@ -27,6 +27,9 @@ import org.apache.commons.logging.LogFactory;
 
 import org.springframework.beans.factory.InitializingBean;
 
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+
 import org.springframework.util.Assert;
 
 import java.io.IOException;
@@ -112,6 +115,14 @@ import javax.servlet.http.HttpServletResponse;
  * <code>exceptionMappings</code> will be redirected to the
  * <code>authenticationFailureUrl</code>
  * </p>
+ * 
+ * <p>
+ * If authentication is successful, an {@link
+ * net.sf.acegisecurity.ui.InteractiveAuthenticationSuccesEvent} will be
+ * published to the application context. No events will be published if
+ * authentication was unsuccessful, because this would generally be recorded
+ * via an <code>AuthenticationManager</code>-specific application event.
+ * </p>
  *
  * @author Ben Alex
  * @author colin sampaleanu
@@ -119,7 +130,7 @@ import javax.servlet.http.HttpServletResponse;
  * @version $Id$
  */
 public abstract class AbstractProcessingFilter implements Filter,
-    InitializingBean {
+    InitializingBean, ApplicationContextAware {
     //~ Static fields/initializers =============================================
 
     public static final String ACEGI_SECURITY_TARGET_URL_KEY = "ACEGI_SECURITY_TARGET_URL";
@@ -128,6 +139,7 @@ public abstract class AbstractProcessingFilter implements Filter,
 
     //~ Instance fields ========================================================
 
+    private ApplicationContext context;
     private AuthenticationManager authenticationManager;
     private Properties exceptionMappings = new Properties();
     private RememberMeServices rememberMeServices = new NullRememberMeServices();
@@ -172,6 +184,10 @@ public abstract class AbstractProcessingFilter implements Filter,
         return alwaysUseDefaultTargetUrl;
     }
 
+    public void setApplicationContext(ApplicationContext context) {
+        this.context = context;
+    }
+
     public void setContinueChainBeforeSuccessfulAuthentication(
         boolean continueChainBeforeSuccessfulAuthentication) {
         this.continueChainBeforeSuccessfulAuthentication = continueChainBeforeSuccessfulAuthentication;
@@ -189,6 +205,14 @@ public abstract class AbstractProcessingFilter implements Filter,
      */
     public abstract String getDefaultFilterProcessesUrl();
 
+    public void setDefaultTargetUrl(String defaultTargetUrl) {
+        this.defaultTargetUrl = defaultTargetUrl;
+    }
+
+    public String getDefaultTargetUrl() {
+        return defaultTargetUrl;
+    }
+
     public void setExceptionMappings(Properties exceptionMappings) {
         this.exceptionMappings = exceptionMappings;
     }
@@ -197,6 +221,14 @@ public abstract class AbstractProcessingFilter implements Filter,
         return new Properties(exceptionMappings);
     }
 
+    public void setFilterProcessesUrl(String filterProcessesUrl) {
+        this.filterProcessesUrl = filterProcessesUrl;
+    }
+
+    public String getFilterProcessesUrl() {
+        return filterProcessesUrl;
+    }
+
     public void setRememberMeServices(RememberMeServices rememberMeServices) {
         this.rememberMeServices = rememberMeServices;
     }
@@ -235,22 +267,6 @@ public abstract class AbstractProcessingFilter implements Filter,
         return authenticationManager;
     }
 
-    public void setDefaultTargetUrl(String defaultTargetUrl) {
-        this.defaultTargetUrl = defaultTargetUrl;
-    }
-
-    public String getDefaultTargetUrl() {
-        return defaultTargetUrl;
-    }
-
-    public void setFilterProcessesUrl(String filterProcessesUrl) {
-        this.filterProcessesUrl = filterProcessesUrl;
-    }
-
-    public String getFilterProcessesUrl() {
-        return filterProcessesUrl;
-    }
-
     public void afterPropertiesSet() throws Exception {
         Assert.hasLength(filterProcessesUrl,
             "filterProcessesUrl must be specified");
@@ -403,6 +419,12 @@ public abstract class AbstractProcessingFilter implements Filter,
 
         rememberMeServices.loginSuccess(request, response, authResult);
 
+        // Fire event
+        if (this.context != null) {
+            context.publishEvent(new InteractiveAuthenticationSuccesEvent(
+                    authResult, this.getClass()));
+        }
+
         response.sendRedirect(response.encodeRedirectURL(targetUrl));
     }
 

+ 71 - 0
core/src/main/java/org/acegisecurity/ui/InteractiveAuthenticationSuccesEvent.java

@@ -0,0 +1,71 @@
+/* Copyright 2004, 2005 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.sf.acegisecurity.ui;
+
+import net.sf.acegisecurity.Authentication;
+
+import org.springframework.context.ApplicationEvent;
+
+import org.springframework.util.Assert;
+
+
+/**
+ * Indicates an interactive authentication was successful.
+ * 
+ * <P>
+ * The <code>ApplicationEvent</code>'s <code>source</code> will be the
+ * <code>Authentication</code> object.
+ * </p>
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class InteractiveAuthenticationSuccesEvent extends ApplicationEvent {
+    //~ Instance fields ========================================================
+
+    private Class generatedBy;
+
+    //~ Constructors ===========================================================
+
+    public InteractiveAuthenticationSuccesEvent(Authentication authentication,
+        Class generatedBy) {
+        super(authentication);
+        Assert.notNull(generatedBy);
+        this.generatedBy = generatedBy;
+    }
+
+    //~ Methods ================================================================
+
+    /**
+     * Getters for the <code>Authentication</code> request that caused the
+     * event. Also available from <code>super.getSource()</code>.
+     *
+     * @return the authentication request
+     */
+    public Authentication getAuthentication() {
+        return (Authentication) super.getSource();
+    }
+
+    /**
+     * Getter for the <code>Class</code> that generated this event. This can be
+     * useful for generating additional logging information.
+     *
+     * @return
+     */
+    public Class getGeneratedBy() {
+        return generatedBy;
+    }
+}

+ 26 - 1
core/src/main/java/org/acegisecurity/ui/rememberme/RememberMeProcessingFilter.java

@@ -16,12 +16,16 @@
 package net.sf.acegisecurity.ui.rememberme;
 
 import net.sf.acegisecurity.context.SecurityContextHolder;
+import net.sf.acegisecurity.ui.InteractiveAuthenticationSuccesEvent;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
 import org.springframework.beans.factory.InitializingBean;
 
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+
 import org.springframework.util.Assert;
 
 import java.io.IOException;
@@ -52,6 +56,14 @@ import javax.servlet.http.HttpServletResponse;
  * will be placed into the <code>SecurityContext</code>.
  * </p>
  * 
+ * <p>
+ * If authentication is successful, an {@link
+ * net.sf.acegisecurity.ui.InteractiveAuthenticationSuccesEvent} will be
+ * published to the application context. No events will be published if
+ * authentication was unsuccessful, because this would generally be recorded
+ * via an <code>AuthenticationManager</code>-specific application event.
+ * </p>
+ * 
  * <P>
  * <B>Do not use this class directly.</B> Instead configure
  * <code>web.xml</code> to use the {@link
@@ -61,17 +73,23 @@ import javax.servlet.http.HttpServletResponse;
  * @author Ben Alex
  * @version $Id$
  */
-public class RememberMeProcessingFilter implements Filter, InitializingBean {
+public class RememberMeProcessingFilter implements Filter, InitializingBean,
+    ApplicationContextAware {
     //~ Static fields/initializers =============================================
 
     private static final Log logger = LogFactory.getLog(RememberMeProcessingFilter.class);
 
     //~ Instance fields ========================================================
 
+    private ApplicationContext context;
     private RememberMeServices rememberMeServices = new NullRememberMeServices();
 
     //~ Methods ================================================================
 
+    public void setApplicationContext(ApplicationContext context) {
+        this.context = context;
+    }
+
     public void setRememberMeServices(RememberMeServices rememberMeServices) {
         this.rememberMeServices = rememberMeServices;
     }
@@ -112,6 +130,13 @@ public class RememberMeProcessingFilter implements Filter, InitializingBean {
                     + SecurityContextHolder.getContext().getAuthentication()
                     + "'");
             }
+
+            // Fire event
+            if (this.context != null) {
+                context.publishEvent(new InteractiveAuthenticationSuccesEvent(
+                        SecurityContextHolder.getContext().getAuthentication(),
+                        this.getClass()));
+            }
         } else {
             if (logger.isDebugEnabled()) {
                 logger.debug(

+ 25 - 1
core/src/main/java/org/acegisecurity/ui/x509/X509ProcessingFilter.java

@@ -21,6 +21,7 @@ import net.sf.acegisecurity.AuthenticationManager;
 import net.sf.acegisecurity.context.SecurityContextHolder;
 import net.sf.acegisecurity.providers.x509.X509AuthenticationToken;
 import net.sf.acegisecurity.ui.AbstractProcessingFilter;
+import net.sf.acegisecurity.ui.InteractiveAuthenticationSuccesEvent;
 import net.sf.acegisecurity.ui.WebAuthenticationDetails;
 
 import org.apache.commons.logging.Log;
@@ -28,6 +29,9 @@ import org.apache.commons.logging.LogFactory;
 
 import org.springframework.beans.factory.InitializingBean;
 
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+
 import org.springframework.util.Assert;
 
 import java.io.IOException;
@@ -55,6 +59,14 @@ import javax.servlet.http.HttpServletResponse;
  * </p>
  * 
  * <p>
+ * If authentication is successful, an {@link
+ * net.sf.acegisecurity.ui.InteractiveAuthenticationSuccesEvent} will be
+ * published to the application context. No events will be published if
+ * authentication was unsuccessful, because this would generally be recorded
+ * via an <code>AuthenticationManager</code>-specific application event.
+ * </p>
+ * 
+ * <p>
  * <b>Do not use this class directly.</b> Instead configure
  * <code>web.xml</code> to use the {@link
  * net.sf.acegisecurity.util.FilterToBeanProxy}.
@@ -63,17 +75,23 @@ import javax.servlet.http.HttpServletResponse;
  * @author Luke Taylor
  * @version $Id$
  */
-public class X509ProcessingFilter implements Filter, InitializingBean {
+public class X509ProcessingFilter implements Filter, InitializingBean,
+    ApplicationContextAware {
     //~ Static fields/initializers =============================================
 
     private static final Log logger = LogFactory.getLog(X509ProcessingFilter.class);
 
     //~ Instance fields ========================================================
 
+    private ApplicationContext context;
     private AuthenticationManager authenticationManager;
 
     //~ Methods ================================================================
 
+    public void setApplicationContext(ApplicationContext context) {
+        this.context = context;
+    }
+
     public void setAuthenticationManager(
         AuthenticationManager authenticationManager) {
         this.authenticationManager = authenticationManager;
@@ -167,6 +185,12 @@ public class X509ProcessingFilter implements Filter, InitializingBean {
         }
 
         SecurityContextHolder.getContext().setAuthentication(authResult);
+
+        // Fire event
+        if (this.context != null) {
+            context.publishEvent(new InteractiveAuthenticationSuccesEvent(
+                    authResult, this.getClass()));
+        }
     }
 
     /**