change AuthenticationProcessingFilter and SecurityEnforcementFilter to use Spring's WebApplicationContextUtils by defualt to find their config context.
This commit is contained in:
@@ -21,7 +21,7 @@ import org.springframework.core.NestedRuntimeException;
|
||||
/**
|
||||
* Abstract superclass for all exceptions thrown in the security package and
|
||||
* subpackages.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Note that this is a runtime (unchecked) exception. Security exceptions are
|
||||
* usually fatal; there is no reason for them to be checked.
|
||||
|
||||
@@ -22,8 +22,12 @@ import net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
import org.springframework.web.context.support.WebApplicationContextUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.Map;
|
||||
@@ -41,12 +45,12 @@ import javax.servlet.http.HttpServletResponse;
|
||||
/**
|
||||
* Wraps requests to the {@link FilterSecurityInterceptor}.
|
||||
*
|
||||
* <P>
|
||||
* This filter is necessary because it provides an application context
|
||||
* environment for the <code>FilterSecurityInterceptor</code> instance.
|
||||
* <p>
|
||||
* This filter is necessary because it provides the bridge between incoming
|
||||
* requests and the <code>FilterSecurityInterceptor</code> instance.
|
||||
* </p>
|
||||
*
|
||||
* <P>
|
||||
* <p>
|
||||
* If a {@link AuthenticationException} is detected, the filter will redirect
|
||||
* to the <code>loginFormUrl</code>. This allows common handling of
|
||||
* authentication failures originating from any subclass of {@link
|
||||
@@ -60,33 +64,55 @@ import javax.servlet.http.HttpServletResponse;
|
||||
* security interceptor.
|
||||
* </p>
|
||||
*
|
||||
* <P>
|
||||
* <p>
|
||||
* This filter works with a <code>FilterSecurityInterceptor</code> instance. By
|
||||
* default, at init time, the filter will use Spring's {@link
|
||||
* WebApplicationContextUtils#getWebApplicationContext(ServletContext sc)}
|
||||
* method to obtain an ApplicationContext instance, inside which must be a
|
||||
* configured <code>FilterSecurityInterceptor</code> instance. In the case
|
||||
* where it is desireable for this filter to instantiate its own
|
||||
* ApplicationContext instance from which to obtain the
|
||||
* <code>FilterSecurityInterceptor</code>, the location of the config for this
|
||||
* context may be specified with the optional
|
||||
* <code>contextConfigLocation</code> init param.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* To use this filter, it is necessary to specify the following filter
|
||||
* initialization parameters:
|
||||
* </p>
|
||||
*
|
||||
* <ul>
|
||||
* <li>
|
||||
* <code>appContextLocation</code> indicates the path to an application context
|
||||
* that contains the <code>FilterSecurityInterceptor</code>.
|
||||
* </li>
|
||||
* <li>
|
||||
* <code>loginFormUrl</code> indicates the URL that should be used for
|
||||
* redirection if an <code>AuthenticationException</code> is detected.
|
||||
* </li>
|
||||
* <li>
|
||||
* <code>contextConfigLocation</code> (optional, normally not used), indicates
|
||||
* the path to an application context that contains a properly configured
|
||||
* <code>FilterSecurityInterceptor</code>. If not specified, {@link
|
||||
* WebApplicationContextUtils#getWebApplicationContext(ServletContext sc)}
|
||||
* will be used to obtain the context.
|
||||
* </li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @author colin sampaleanu
|
||||
* @version $Id$
|
||||
*/
|
||||
public class SecurityEnforcementFilter implements Filter {
|
||||
//~ Static fields/initializers =============================================
|
||||
|
||||
/**
|
||||
* Name of (optional) servlet filter parameter that can specify the config
|
||||
* location for a new ApplicationContext used to config this filter.
|
||||
*/
|
||||
public static final String CONFIG_LOCATION_PARAM = "contextConfigLocation";
|
||||
private static final Log logger = LogFactory.getLog(SecurityEnforcementFilter.class);
|
||||
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
protected ClassPathXmlApplicationContext ctx;
|
||||
protected FilterSecurityInterceptor securityInterceptor;
|
||||
|
||||
/**
|
||||
@@ -94,11 +120,15 @@ public class SecurityEnforcementFilter implements Filter {
|
||||
* <code>AuthenticationException</code> is detected.
|
||||
*/
|
||||
protected String loginFormUrl;
|
||||
private ApplicationContext ctx;
|
||||
private boolean ourContext = false;
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void destroy() {
|
||||
ctx.close();
|
||||
if (ourContext && ctx instanceof ConfigurableApplicationContext) {
|
||||
((ConfigurableApplicationContext) ctx).close();
|
||||
}
|
||||
}
|
||||
|
||||
public void doFilter(ServletRequest request, ServletResponse response,
|
||||
@@ -145,15 +175,15 @@ public class SecurityEnforcementFilter implements Filter {
|
||||
}
|
||||
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
String appContextLocation = filterConfig.getInitParameter(
|
||||
"appContextLocation");
|
||||
String appContextLocation = filterConfig.getInitParameter(CONFIG_LOCATION_PARAM);
|
||||
|
||||
if ((appContextLocation == null) || "".equals(appContextLocation)) {
|
||||
throw new ServletException("appContextLocation must be specified");
|
||||
}
|
||||
if ((appContextLocation != null) && (appContextLocation.length() > 0)) {
|
||||
ourContext = true;
|
||||
|
||||
if (Thread.currentThread().getContextClassLoader().getResource(appContextLocation) == null) {
|
||||
throw new ServletException("Cannot locate " + appContextLocation);
|
||||
if (Thread.currentThread().getContextClassLoader().getResource(appContextLocation) == null) {
|
||||
throw new ServletException("Cannot locate "
|
||||
+ appContextLocation);
|
||||
}
|
||||
}
|
||||
|
||||
loginFormUrl = filterConfig.getInitParameter("loginFormUrl");
|
||||
@@ -162,7 +192,21 @@ public class SecurityEnforcementFilter implements Filter {
|
||||
throw new ServletException("loginFormUrl must be specified");
|
||||
}
|
||||
|
||||
ctx = new ClassPathXmlApplicationContext(appContextLocation);
|
||||
try {
|
||||
if (!ourContext) {
|
||||
ctx = WebApplicationContextUtils
|
||||
.getRequiredWebApplicationContext(filterConfig
|
||||
.getServletContext());
|
||||
} else {
|
||||
ctx = new ClassPathXmlApplicationContext(appContextLocation);
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
throw new ServletException(
|
||||
"Error obtaining/creating ApplicationContext for config. Must be stored in ServletContext, or optionally '"
|
||||
+ CONFIG_LOCATION_PARAM
|
||||
+ "' param may be used to allow creation of new context by this filter. See root error for additional details",
|
||||
e);
|
||||
}
|
||||
|
||||
Map beans = ctx.getBeansOfType(FilterSecurityInterceptor.class, true,
|
||||
true);
|
||||
|
||||
@@ -23,8 +23,12 @@ import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
import org.springframework.web.context.support.WebApplicationContextUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.Map;
|
||||
@@ -52,30 +56,39 @@ import javax.servlet.http.HttpServletResponse;
|
||||
* HttpSessionIntegrationFilter#ACEGI_SECURITY_AUTHENTICATION_KEY}.
|
||||
* </p>
|
||||
*
|
||||
* <P>
|
||||
* <p>
|
||||
* Login forms must present two parameters to this filter: a username and
|
||||
* password. The filter will process the login against the authentication
|
||||
* environment that was configured from a Spring application context defined
|
||||
* in the filter initialization.
|
||||
* </p>
|
||||
*
|
||||
* <P>
|
||||
* <p>
|
||||
* If authentication fails, the <code>AuthenticationException</code> will be
|
||||
* placed into the <code>HttpSession</code> with the attribute defined by
|
||||
* {@link #ACEGI_SECURITY_LAST_EXCEPTION_KEY}.
|
||||
* </p>
|
||||
*
|
||||
* <P>
|
||||
* <p>
|
||||
* This filter works with an {@link AuthenticationManager} which is used to
|
||||
* process each authentication request. By default, at init time, the filter
|
||||
* will use Spring's {@link
|
||||
* WebApplicationContextUtils#getWebApplicationContext(ServletContext sc)}
|
||||
* method to obtain an ApplicationContext instance, inside which must be a
|
||||
* configured AuthenticationManager instance. In the case where it is
|
||||
* desireable for this filter to instantiate its own ApplicationContext
|
||||
* instance from which to obtain the AuthenticationManager, the location of
|
||||
* the config for this context may be specified with the optional
|
||||
* <code>appContextLocation</code> init param.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* To use this filter, it is necessary to specify the following filter
|
||||
* initialization parameters:
|
||||
* </p>
|
||||
*
|
||||
* <ul>
|
||||
* <li>
|
||||
* <code>appContextLocation</code> indicates the path to an application context
|
||||
* that contains an {@link AuthenticationManager} that should be used to
|
||||
* process each authentication request.
|
||||
* </li>
|
||||
* <li>
|
||||
* <code>defaultTargetUrl</code> indicates the URL that should be used for
|
||||
* redirection if the <code>HttpSession</code> attribute named {@link
|
||||
* #ACEGI_SECURITY_TARGET_URL_KEY} does not indicate the target URL once
|
||||
@@ -91,15 +104,29 @@ import javax.servlet.http.HttpServletResponse;
|
||||
* respond to. This parameter is optional, and defaults to
|
||||
* <code>/j_acegi_security_check</code>.
|
||||
* </li>
|
||||
* <li>
|
||||
* <code>appContextLocation</code> (optional, normally not used), indicates the
|
||||
* path to an application context that contains an {@link
|
||||
* AuthenticationManager} which should be used to process each authentication
|
||||
* request. If not specified, {@link
|
||||
* WebApplicationContextUtils#getWebApplicationContext(ServletContext sc)}
|
||||
* will be used to obtain the context.
|
||||
* </li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @author colin sampaleanu
|
||||
* @version $Id$
|
||||
*/
|
||||
public class AuthenticationProcessingFilter implements Filter {
|
||||
//~ Static fields/initializers =============================================
|
||||
|
||||
/**
|
||||
* Name of (optional) servlet filter parameter that can specify the config
|
||||
* location for a new ApplicationContext used to config this filter.
|
||||
*/
|
||||
public static final String CONFIG_LOCATION_PARAM = "appContextLocation";
|
||||
public static final String ACEGI_SECURITY_TARGET_URL_KEY = "ACEGI_SECURITY_TARGET_URL";
|
||||
public static final String ACEGI_SECURITY_FORM_USERNAME_KEY = "j_username";
|
||||
public static final String ACEGI_SECURITY_FORM_PASSWORD_KEY = "j_password";
|
||||
@@ -108,8 +135,8 @@ public class AuthenticationProcessingFilter implements Filter {
|
||||
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private ApplicationContext ctx;
|
||||
private AuthenticationManager authenticationManager;
|
||||
private ClassPathXmlApplicationContext ctx;
|
||||
|
||||
/** Where to redirect the browser to if authentication fails */
|
||||
private String authenticationFailureUrl;
|
||||
@@ -125,11 +152,14 @@ public class AuthenticationProcessingFilter implements Filter {
|
||||
* <code>/j_acegi_security_check</code>)
|
||||
*/
|
||||
private String filterProcessesUrl;
|
||||
private boolean ourContext = false;
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void destroy() {
|
||||
ctx.close();
|
||||
if (ourContext && ctx instanceof ConfigurableApplicationContext) {
|
||||
((ConfigurableApplicationContext) ctx).close();
|
||||
}
|
||||
}
|
||||
|
||||
public void doFilter(ServletRequest request, ServletResponse response,
|
||||
@@ -216,15 +246,15 @@ public class AuthenticationProcessingFilter implements Filter {
|
||||
}
|
||||
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
String appContextLocation = filterConfig.getInitParameter(
|
||||
"appContextLocation");
|
||||
String appContextLocation = filterConfig.getInitParameter(CONFIG_LOCATION_PARAM);
|
||||
|
||||
if ((appContextLocation == null) || "".equals(appContextLocation)) {
|
||||
throw new ServletException("appContextLocation must be specified");
|
||||
}
|
||||
if ((appContextLocation != null) && (appContextLocation.length() > 0)) {
|
||||
ourContext = true;
|
||||
|
||||
if (Thread.currentThread().getContextClassLoader().getResource(appContextLocation) == null) {
|
||||
throw new ServletException("Cannot locate " + appContextLocation);
|
||||
if (Thread.currentThread().getContextClassLoader().getResource(appContextLocation) == null) {
|
||||
throw new ServletException("Cannot locate "
|
||||
+ appContextLocation);
|
||||
}
|
||||
}
|
||||
|
||||
defaultTargetUrl = filterConfig.getInitParameter("defaultTargetUrl");
|
||||
@@ -248,7 +278,21 @@ public class AuthenticationProcessingFilter implements Filter {
|
||||
filterProcessesUrl = "/j_acegi_security_check";
|
||||
}
|
||||
|
||||
ctx = new ClassPathXmlApplicationContext(appContextLocation);
|
||||
try {
|
||||
if (!ourContext) {
|
||||
ctx = WebApplicationContextUtils
|
||||
.getRequiredWebApplicationContext(filterConfig
|
||||
.getServletContext());
|
||||
} else {
|
||||
ctx = new ClassPathXmlApplicationContext(appContextLocation);
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
throw new ServletException(
|
||||
"Error obtaining/creating ApplicationContext for config. Must be stored in ServletContext, or optionally '"
|
||||
+ CONFIG_LOCATION_PARAM
|
||||
+ "' param may be used to allow creation of new context by this filter. See root error for additional details",
|
||||
e);
|
||||
}
|
||||
|
||||
Map beans = ctx.getBeansOfType(AuthenticationManager.class, true, true);
|
||||
|
||||
|
||||
@@ -150,8 +150,7 @@ public class SecurityEnforcementFilterTests extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testStartupDetectsMissingAppContextLocation()
|
||||
throws Exception {
|
||||
public void testStartupDetectsMissingAppContext() throws Exception {
|
||||
MockFilterConfig config = new MockFilterConfig();
|
||||
config.setInitParmeter("loginFormUrl", "/login.jsp");
|
||||
|
||||
@@ -161,8 +160,7 @@ public class SecurityEnforcementFilterTests extends TestCase {
|
||||
filter.init(config);
|
||||
fail("Should have thrown ServletException");
|
||||
} catch (ServletException expected) {
|
||||
assertEquals("appContextLocation must be specified",
|
||||
expected.getMessage());
|
||||
assertTrue(expected.getMessage().startsWith("Error obtaining/creating ApplicationContext for config."));
|
||||
}
|
||||
|
||||
config.setInitParmeter("appContextLocation", "");
|
||||
@@ -171,8 +169,7 @@ public class SecurityEnforcementFilterTests extends TestCase {
|
||||
filter.init(config);
|
||||
fail("Should have thrown ServletException");
|
||||
} catch (ServletException expected) {
|
||||
assertEquals("appContextLocation must be specified",
|
||||
expected.getMessage());
|
||||
assertTrue(expected.getMessage().startsWith("Error obtaining/creating ApplicationContext for config."));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -287,8 +287,7 @@ public class AuthenticationProcessingFilterTests extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testStartupDetectsMissingAppContextLocation()
|
||||
throws Exception {
|
||||
public void testStartupDetectsMissingAppContext() throws Exception {
|
||||
MockFilterConfig config = new MockFilterConfig();
|
||||
config.setInitParmeter("defaultTargetUrl", "/");
|
||||
config.setInitParmeter("authenticationFailureUrl", "/failed.jsp");
|
||||
@@ -299,8 +298,7 @@ public class AuthenticationProcessingFilterTests extends TestCase {
|
||||
filter.init(config);
|
||||
fail("Should have thrown ServletException");
|
||||
} catch (ServletException expected) {
|
||||
assertEquals("appContextLocation must be specified",
|
||||
expected.getMessage());
|
||||
assertTrue(expected.getMessage().startsWith("Error obtaining/creating ApplicationContext for config."));
|
||||
}
|
||||
|
||||
config.setInitParmeter("appContextLocation", "");
|
||||
@@ -309,8 +307,7 @@ public class AuthenticationProcessingFilterTests extends TestCase {
|
||||
filter.init(config);
|
||||
fail("Should have thrown ServletException");
|
||||
} catch (ServletException expected) {
|
||||
assertEquals("appContextLocation must be specified",
|
||||
expected.getMessage());
|
||||
assertTrue(expected.getMessage().startsWith("Error obtaining/creating ApplicationContext for config."));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user