2
0
Эх сурвалжийг харах

AbstractProcessingFilter no longer uses a set*FailureUrl approach for every exception, it now uses a properties object that maps authenticationExceptions to failure urls

Ray Krueger 20 жил өмнө
parent
commit
9649003d57

+ 41 - 128
core/src/main/java/org/acegisecurity/ui/AbstractProcessingFilter.java

@@ -18,15 +18,9 @@ package net.sf.acegisecurity.ui;
 import net.sf.acegisecurity.Authentication;
 import net.sf.acegisecurity.AuthenticationException;
 import net.sf.acegisecurity.AuthenticationManager;
-import net.sf.acegisecurity.AuthenticationServiceException;
-import net.sf.acegisecurity.BadCredentialsException;
-import net.sf.acegisecurity.CredentialsExpiredException;
-import net.sf.acegisecurity.DisabledException;
-import net.sf.acegisecurity.LockedException;
 import net.sf.acegisecurity.context.ContextHolder;
 import net.sf.acegisecurity.context.security.SecureContext;
 import net.sf.acegisecurity.context.security.SecureContextUtils;
-import net.sf.acegisecurity.providers.cas.ProxyUntrustedException;
 import net.sf.acegisecurity.ui.rememberme.NullRememberMeServices;
 import net.sf.acegisecurity.ui.rememberme.RememberMeServices;
 
@@ -39,12 +33,9 @@ import org.springframework.util.Assert;
 
 import java.io.IOException;
 
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
+import java.util.Properties;
+
+import javax.servlet.*;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
@@ -95,9 +86,33 @@ import javax.servlet.http.HttpServletResponse;
  * </li>
  * </ul>
  * 
+ * <p>
+ * To configure this filter to redirect to specfic pages as the result of
+ * specific {@link AuthenticationException}s you can do the following.
+ * Configure the <code>exceptionMappings</code> property in your application
+ * xml. This property is a java.util.Properties object that maps a
+ * fully-qualified exception class name to a redirection url target.<br>
+ * For example:<br>
+ * <code> &lt;property name="exceptionMappings"&gt;<br>
+ * &nbsp;&nbsp;&lt;props&gt;<br>
+ * &nbsp;&nbsp;&nbsp;&nbsp;&lt;prop&gt; key="net.sf.acegisecurity.BadCredentialsException"&gt;/bad_credentials.jsp&lt;/prop&gt;<br>
+ * &nbsp;&nbsp;&lt;/props&gt;<br>
+ * &lt;/property&gt;<br>
+ * </code><br>
+ * The example above would redirect all {@link
+ * net.sf.acegisecurity.BadCredentialsException}s thrown, to a page in the
+ * web-application called /bad_credentials.jsp.
+ * </p>
+ * 
+ * <p>
+ * Any {@link AuthenticationException} thrown that cannot be matched in the
+ * <code>exceptionMappings</code> will be redirected to the
+ * <code>authenticationFailureUrl</code>
+ * </p>
  *
  * @author Ben Alex
  * @author colin sampaleanu
+ * @author Ray Krueger
  * @version $Id$
  */
 public abstract class AbstractProcessingFilter implements Filter,
@@ -111,42 +126,12 @@ public abstract class AbstractProcessingFilter implements Filter,
     //~ Instance fields ========================================================
 
     private AuthenticationManager authenticationManager;
+    private Properties exceptionMappings = new Properties();
     private RememberMeServices rememberMeServices = new NullRememberMeServices();
 
-    /**
-     * Where to redirect the browser if authentication fails due to incorrect
-     * credentials
-     */
-    private String authenticationCredentialCheckFailureUrl;
-
-    /**
-     * Where to redirect the browser if authentication fails due to the users
-     * account being disabled
-     */
-    private String authenticationDisabledFailureUrl;
-
     /** Where to redirect the browser to if authentication fails */
     private String authenticationFailureUrl;
 
-    /**
-     * Where to redirect the browser if authentication fails due to the users
-     * account being locked
-     */
-    private String authenticationLockedFailureUrl;
-
-    /**
-     * Where to redirect the browser if authentication fails due to the user's
-     * proxy being considered untrusted
-     */
-    private String authenticationProxyUntrustedFailureUrl;
-
-    /**
-     * Where to redirect the browser if authentication fails due to failure of
-     * the authentication service
-     */
-    private String authenticationServiceFailureUrl;
-    private String credentialsExpiredFailureUrl;
-
     /**
      * Where to redirect the browser to if authentication is successful but
      * ACEGI_SECURITY_TARGET_URL_KEY is <code>null</code>
@@ -201,6 +186,14 @@ public abstract class AbstractProcessingFilter implements Filter,
      */
     public abstract String getDefaultFilterProcessesUrl();
 
+    public void setExceptionMappings(Properties exceptionMappings) {
+        this.exceptionMappings = exceptionMappings;
+    }
+
+    public Properties getExceptionMappings() {
+        return new Properties(exceptionMappings);
+    }
+
     public void setRememberMeServices(RememberMeServices rememberMeServices) {
         this.rememberMeServices = rememberMeServices;
     }
@@ -222,24 +215,6 @@ public abstract class AbstractProcessingFilter implements Filter,
     public abstract Authentication attemptAuthentication(
         HttpServletRequest request) throws AuthenticationException;
 
-    public void setAuthenticationCredentialCheckFailureUrl(
-        String authenticationCredentialCheckFailureUrl) {
-        this.authenticationCredentialCheckFailureUrl = authenticationCredentialCheckFailureUrl;
-    }
-
-    public String getAuthenticationCredentialCheckFailureUrl() {
-        return authenticationCredentialCheckFailureUrl;
-    }
-
-    public void setAuthenticationDisabledFailureUrl(
-        String authenticationDisabledFailureUrl) {
-        this.authenticationDisabledFailureUrl = authenticationDisabledFailureUrl;
-    }
-
-    public String getAuthenticationDisabledFailureUrl() {
-        return authenticationDisabledFailureUrl;
-    }
-
     public void setAuthenticationFailureUrl(String authenticationFailureUrl) {
         this.authenticationFailureUrl = authenticationFailureUrl;
     }
@@ -248,15 +223,6 @@ public abstract class AbstractProcessingFilter implements Filter,
         return authenticationFailureUrl;
     }
 
-    public void setAuthenticationLockedFailureUrl(
-        String authenticationLockedFailureUrl) {
-        this.authenticationLockedFailureUrl = authenticationLockedFailureUrl;
-    }
-
-    public String getAuthenticationLockedFailureUrl() {
-        return authenticationLockedFailureUrl;
-    }
-
     public void setAuthenticationManager(
         AuthenticationManager authenticationManager) {
         this.authenticationManager = authenticationManager;
@@ -266,33 +232,6 @@ public abstract class AbstractProcessingFilter implements Filter,
         return authenticationManager;
     }
 
-    public void setAuthenticationProxyUntrustedFailureUrl(
-        String authenticationProxyUntrustedFailureUrl) {
-        this.authenticationProxyUntrustedFailureUrl = authenticationProxyUntrustedFailureUrl;
-    }
-
-    public String getAuthenticationProxyUntrustedFailureUrl() {
-        return authenticationProxyUntrustedFailureUrl;
-    }
-
-    public void setAuthenticationServiceFailureUrl(
-        String authenticationServiceFailureUrl) {
-        this.authenticationServiceFailureUrl = authenticationServiceFailureUrl;
-    }
-
-    public String getAuthenticationServiceFailureUrl() {
-        return authenticationServiceFailureUrl;
-    }
-
-    public void setCredentialsExpiredFailureUrl(
-        String credentialsExpiredFailureUrl) {
-        this.credentialsExpiredFailureUrl = credentialsExpiredFailureUrl;
-    }
-
-    public String getCredentialsExpiredFailureUrl() {
-        return credentialsExpiredFailureUrl;
-    }
-
     public void setDefaultTargetUrl(String defaultTargetUrl) {
         this.defaultTargetUrl = defaultTargetUrl;
     }
@@ -403,8 +342,10 @@ public abstract class AbstractProcessingFilter implements Filter,
         HttpServletResponse response) throws IOException {}
 
     /**
+     * <p>
      * Indicates whether this filter should attempt to process a login request
      * for the current invocation.
+     * </p>
      * 
      * <p>
      * Subclasses may override for special requirements, such as Tapestry
@@ -474,37 +415,9 @@ public abstract class AbstractProcessingFilter implements Filter,
             logger.debug("Updated ContextHolder to contain null Authentication");
         }
 
-        String failureUrl = authenticationFailureUrl;
-
-        if (failed instanceof AuthenticationServiceException
-            && (authenticationServiceFailureUrl != null)) {
-            failureUrl = authenticationServiceFailureUrl;
-        }
-
-        if (failed instanceof BadCredentialsException
-            && (this.authenticationCredentialCheckFailureUrl != null)) {
-            failureUrl = authenticationCredentialCheckFailureUrl;
-        }
-
-        if (failed instanceof DisabledException
-            && (authenticationDisabledFailureUrl != null)) {
-            failureUrl = authenticationDisabledFailureUrl;
-        }
-
-        if (failed instanceof LockedException
-            && (authenticationLockedFailureUrl != null)) {
-            failureUrl = authenticationLockedFailureUrl;
-        }
-
-        if (failed instanceof ProxyUntrustedException
-            && (authenticationProxyUntrustedFailureUrl != null)) {
-            failureUrl = authenticationProxyUntrustedFailureUrl;
-        }
-
-        if (failed instanceof CredentialsExpiredException
-            && (credentialsExpiredFailureUrl != null)) {
-            failureUrl = credentialsExpiredFailureUrl;
-        }
+        String failureUrl = exceptionMappings.getProperty(failed.getClass()
+                                                                .getName(),
+                authenticationFailureUrl);
 
         if (logger.isDebugEnabled()) {
             logger.debug("Authentication request failed: " + failed.toString());

+ 22 - 32
core/src/test/java/org/acegisecurity/ui/AbstractProcessingFilterTests.java

@@ -17,15 +17,7 @@ package net.sf.acegisecurity.ui;
 
 import junit.framework.TestCase;
 
-import net.sf.acegisecurity.Authentication;
-import net.sf.acegisecurity.AuthenticationException;
-import net.sf.acegisecurity.BadCredentialsException;
-import net.sf.acegisecurity.GrantedAuthority;
-import net.sf.acegisecurity.GrantedAuthorityImpl;
-import net.sf.acegisecurity.MockAuthenticationManager;
-import net.sf.acegisecurity.MockFilterConfig;
-import net.sf.acegisecurity.MockHttpServletRequest;
-import net.sf.acegisecurity.MockHttpServletResponse;
+import net.sf.acegisecurity.*;
 import net.sf.acegisecurity.context.ContextHolder;
 import net.sf.acegisecurity.context.security.SecureContextImpl;
 import net.sf.acegisecurity.context.security.SecureContextUtils;
@@ -34,12 +26,9 @@ import net.sf.acegisecurity.ui.rememberme.TokenBasedRememberMeServices;
 
 import java.io.IOException;
 
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
+import java.util.Properties;
+
+import javax.servlet.*;
 import javax.servlet.http.HttpServletRequest;
 
 
@@ -115,8 +104,26 @@ public class AbstractProcessingFilterTests extends TestCase {
         // Test
         executeFilterInContainerSimulator(config, filter, request, response,
             chain);
+
         assertEquals("/myApp/failed.jsp", response.getRedirect());
         assertNull(SecureContextUtils.getSecureContext().getAuthentication());
+
+        //Prepare again, this time using the exception mapping
+        filter = new MockAbstractProcessingFilter(new AccountExpiredException(
+                    "You're account is expired"));
+        filter.setAuthenticationFailureUrl("/myApp/failed.jsp");
+
+        Properties exceptionMappings = filter.getExceptionMappings();
+        exceptionMappings.setProperty(AccountExpiredException.class.getName(),
+            "/myApp/accountExpired.jsp");
+        filter.setExceptionMappings(exceptionMappings);
+
+        // Test
+        executeFilterInContainerSimulator(config, filter, request, response,
+            chain);
+
+        assertEquals("/myApp/accountExpired.jsp", response.getRedirect());
+        assertNull(SecureContextUtils.getSecureContext().getAuthentication());
     }
 
     public void testFilterProcessesUrlVariationsRespected()
@@ -168,25 +175,8 @@ public class AbstractProcessingFilterTests extends TestCase {
         filter.setFilterProcessesUrl("/p");
         assertEquals("/p", filter.getFilterProcessesUrl());
 
-        filter.setAuthenticationCredentialCheckFailureUrl("/foo");
-        assertEquals("/foo", filter.getAuthenticationCredentialCheckFailureUrl());
-
-        filter.setAuthenticationDisabledFailureUrl("/dis");
-        assertEquals("/dis", filter.getAuthenticationDisabledFailureUrl());
-
         filter.setAuthenticationFailureUrl("/fail");
         assertEquals("/fail", filter.getAuthenticationFailureUrl());
-
-        filter.setAuthenticationLockedFailureUrl("/locked");
-        assertEquals("/locked", filter.getAuthenticationLockedFailureUrl());
-
-        filter.setAuthenticationProxyUntrustedFailureUrl("/proxy");
-        assertEquals("/proxy",
-            filter.getAuthenticationProxyUntrustedFailureUrl());
-
-        filter.setAuthenticationServiceFailureUrl("/serviceFailure");
-        assertEquals("/serviceFailure",
-            filter.getAuthenticationServiceFailureUrl());
     }
 
     public void testIgnoresAnyServletPathOtherThanFilterProcessesUrl()

+ 1 - 0
doc/xdocs/changes.xml

@@ -31,6 +31,7 @@
       <action dev="benalex" type="fix">Handle null Authentication.getAuthorities() in AuthorizeTag</action>
       <action dev="benalex" type="update">Add credentialsExpiredFailureUrl getter/setter to AbstractProcessingFilter</action>
       <action dev="benalex" type="update">Update commons-codec dependency to 1.3</action>
+      <action dev="raykrueger" type="update">AbstractProcessingFilter no longer has setters for failures, it uses the exceptionMappings property</action>
     </release>
     <release version="0.8.1" date="2005-03-22">
       <action dev="luke_t" type="add">X509 (certificate-based) authentication support</action>