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

This commit is contained in:
Ray Krueger 2005-03-28 17:42:21 +00:00
parent 798ebb1a3d
commit 9649003d57
3 changed files with 64 additions and 160 deletions

View File

@ -18,15 +18,9 @@ package net.sf.acegisecurity.ui;
import net.sf.acegisecurity.Authentication; import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.AuthenticationException; import net.sf.acegisecurity.AuthenticationException;
import net.sf.acegisecurity.AuthenticationManager; 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.ContextHolder;
import net.sf.acegisecurity.context.security.SecureContext; import net.sf.acegisecurity.context.security.SecureContext;
import net.sf.acegisecurity.context.security.SecureContextUtils; 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.NullRememberMeServices;
import net.sf.acegisecurity.ui.rememberme.RememberMeServices; import net.sf.acegisecurity.ui.rememberme.RememberMeServices;
@ -39,12 +33,9 @@ import org.springframework.util.Assert;
import java.io.IOException; import java.io.IOException;
import javax.servlet.Filter; import java.util.Properties;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig; import javax.servlet.*;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@ -95,9 +86,33 @@ import javax.servlet.http.HttpServletResponse;
* </li> * </li>
* </ul> * </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 Ben Alex
* @author colin sampaleanu * @author colin sampaleanu
* @author Ray Krueger
* @version $Id$ * @version $Id$
*/ */
public abstract class AbstractProcessingFilter implements Filter, public abstract class AbstractProcessingFilter implements Filter,
@ -111,42 +126,12 @@ public abstract class AbstractProcessingFilter implements Filter,
//~ Instance fields ======================================================== //~ Instance fields ========================================================
private AuthenticationManager authenticationManager; private AuthenticationManager authenticationManager;
private Properties exceptionMappings = new Properties();
private RememberMeServices rememberMeServices = new NullRememberMeServices(); 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 */ /** Where to redirect the browser to if authentication fails */
private String authenticationFailureUrl; 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 * Where to redirect the browser to if authentication is successful but
* ACEGI_SECURITY_TARGET_URL_KEY is <code>null</code> * ACEGI_SECURITY_TARGET_URL_KEY is <code>null</code>
@ -201,6 +186,14 @@ public abstract class AbstractProcessingFilter implements Filter,
*/ */
public abstract String getDefaultFilterProcessesUrl(); public abstract String getDefaultFilterProcessesUrl();
public void setExceptionMappings(Properties exceptionMappings) {
this.exceptionMappings = exceptionMappings;
}
public Properties getExceptionMappings() {
return new Properties(exceptionMappings);
}
public void setRememberMeServices(RememberMeServices rememberMeServices) { public void setRememberMeServices(RememberMeServices rememberMeServices) {
this.rememberMeServices = rememberMeServices; this.rememberMeServices = rememberMeServices;
} }
@ -222,24 +215,6 @@ public abstract class AbstractProcessingFilter implements Filter,
public abstract Authentication attemptAuthentication( public abstract Authentication attemptAuthentication(
HttpServletRequest request) throws AuthenticationException; 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) { public void setAuthenticationFailureUrl(String authenticationFailureUrl) {
this.authenticationFailureUrl = authenticationFailureUrl; this.authenticationFailureUrl = authenticationFailureUrl;
} }
@ -248,15 +223,6 @@ public abstract class AbstractProcessingFilter implements Filter,
return authenticationFailureUrl; return authenticationFailureUrl;
} }
public void setAuthenticationLockedFailureUrl(
String authenticationLockedFailureUrl) {
this.authenticationLockedFailureUrl = authenticationLockedFailureUrl;
}
public String getAuthenticationLockedFailureUrl() {
return authenticationLockedFailureUrl;
}
public void setAuthenticationManager( public void setAuthenticationManager(
AuthenticationManager authenticationManager) { AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager; this.authenticationManager = authenticationManager;
@ -266,33 +232,6 @@ public abstract class AbstractProcessingFilter implements Filter,
return authenticationManager; 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) { public void setDefaultTargetUrl(String defaultTargetUrl) {
this.defaultTargetUrl = defaultTargetUrl; this.defaultTargetUrl = defaultTargetUrl;
} }
@ -403,8 +342,10 @@ public abstract class AbstractProcessingFilter implements Filter,
HttpServletResponse response) throws IOException {} HttpServletResponse response) throws IOException {}
/** /**
* <p>
* Indicates whether this filter should attempt to process a login request * Indicates whether this filter should attempt to process a login request
* for the current invocation. * for the current invocation.
* </p>
* *
* <p> * <p>
* Subclasses may override for special requirements, such as Tapestry * 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"); logger.debug("Updated ContextHolder to contain null Authentication");
} }
String failureUrl = authenticationFailureUrl; String failureUrl = exceptionMappings.getProperty(failed.getClass()
.getName(),
if (failed instanceof AuthenticationServiceException authenticationFailureUrl);
&& (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;
}
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Authentication request failed: " + failed.toString()); logger.debug("Authentication request failed: " + failed.toString());

View File

@ -17,15 +17,7 @@ package net.sf.acegisecurity.ui;
import junit.framework.TestCase; import junit.framework.TestCase;
import net.sf.acegisecurity.Authentication; import net.sf.acegisecurity.*;
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.context.ContextHolder; import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.security.SecureContextImpl; import net.sf.acegisecurity.context.security.SecureContextImpl;
import net.sf.acegisecurity.context.security.SecureContextUtils; import net.sf.acegisecurity.context.security.SecureContextUtils;
@ -34,12 +26,9 @@ import net.sf.acegisecurity.ui.rememberme.TokenBasedRememberMeServices;
import java.io.IOException; import java.io.IOException;
import javax.servlet.Filter; import java.util.Properties;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig; import javax.servlet.*;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -115,8 +104,26 @@ public class AbstractProcessingFilterTests extends TestCase {
// Test // Test
executeFilterInContainerSimulator(config, filter, request, response, executeFilterInContainerSimulator(config, filter, request, response,
chain); chain);
assertEquals("/myApp/failed.jsp", response.getRedirect()); assertEquals("/myApp/failed.jsp", response.getRedirect());
assertNull(SecureContextUtils.getSecureContext().getAuthentication()); 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() public void testFilterProcessesUrlVariationsRespected()
@ -168,25 +175,8 @@ public class AbstractProcessingFilterTests extends TestCase {
filter.setFilterProcessesUrl("/p"); filter.setFilterProcessesUrl("/p");
assertEquals("/p", filter.getFilterProcessesUrl()); assertEquals("/p", filter.getFilterProcessesUrl());
filter.setAuthenticationCredentialCheckFailureUrl("/foo");
assertEquals("/foo", filter.getAuthenticationCredentialCheckFailureUrl());
filter.setAuthenticationDisabledFailureUrl("/dis");
assertEquals("/dis", filter.getAuthenticationDisabledFailureUrl());
filter.setAuthenticationFailureUrl("/fail"); filter.setAuthenticationFailureUrl("/fail");
assertEquals("/fail", filter.getAuthenticationFailureUrl()); 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() public void testIgnoresAnyServletPathOtherThanFilterProcessesUrl()

View File

@ -31,6 +31,7 @@
<action dev="benalex" type="fix">Handle null Authentication.getAuthorities() in AuthorizeTag</action> <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">Add credentialsExpiredFailureUrl getter/setter to AbstractProcessingFilter</action>
<action dev="benalex" type="update">Update commons-codec dependency to 1.3</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>
<release version="0.8.1" date="2005-03-22"> <release version="0.8.1" date="2005-03-22">
<action dev="luke_t" type="add">X509 (certificate-based) authentication support</action> <action dev="luke_t" type="add">X509 (certificate-based) authentication support</action>