diff --git a/build.xml b/build.xml index b9060b0042..1eba49fdeb 100644 --- a/build.xml +++ b/build.xml @@ -182,6 +182,7 @@ + @@ -202,6 +203,7 @@ + @@ -221,6 +223,7 @@ + @@ -240,6 +243,7 @@ + @@ -258,7 +262,6 @@ - diff --git a/core/src/main/java/org/acegisecurity/intercept/web/SecurityEnforcementFilter.java b/core/src/main/java/org/acegisecurity/intercept/web/SecurityEnforcementFilter.java index 86c6307cdb..32f816826f 100644 --- a/core/src/main/java/org/acegisecurity/intercept/web/SecurityEnforcementFilter.java +++ b/core/src/main/java/org/acegisecurity/intercept/web/SecurityEnforcementFilter.java @@ -22,16 +22,10 @@ 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 org.springframework.beans.factory.InitializingBean; import java.io.IOException; -import java.util.Map; - import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; @@ -65,72 +59,79 @@ import javax.servlet.http.HttpServletResponse; *

* *

- * This filter works with a FilterSecurityInterceptor 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 FilterSecurityInterceptor instance. In the case - * where it is desireable for this filter to instantiate its own - * ApplicationContext instance from which to obtain the - * FilterSecurityInterceptor, the location of the config for this - * context may be specified with the optional - * contextConfigLocation init param. - *

- * - *

* To use this filter, it is necessary to specify the following filter * initialization parameters: *

* *
    *
  • + * filterSecurityInterceptor indicates the + * FilterSecurityInterceptor to delegate HTTP security decisions + * to. + *
  • + *
  • * loginFormUrl indicates the URL that should be used for * redirection if an AuthenticationException is detected. *
  • - *
  • - * contextConfigLocation (optional, normally not used), indicates - * the path to an application context that contains a properly configured - * FilterSecurityInterceptor. If not specified, {@link - * WebApplicationContextUtils#getWebApplicationContext(ServletContext sc)} - * will be used to obtain the context. - *
  • *
* + *

+ * Do not use this class directly. Instead configure + * web.xml to use the {@link + * net.sf.acegisecurity.util.FilterToBeanProxy}. + *

* * @author Ben Alex * @author colin sampaleanu * @version $Id$ */ -public class SecurityEnforcementFilter implements Filter { +public class SecurityEnforcementFilter implements Filter, InitializingBean { //~ 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 FilterSecurityInterceptor securityInterceptor; + protected FilterSecurityInterceptor filterSecurityInterceptor; /** * The URL that should be used for redirection if an * AuthenticationException is detected. */ protected String loginFormUrl; - private ApplicationContext ctx; - private boolean ourContext = false; //~ Methods ================================================================ - public void destroy() { - if (ourContext && ctx instanceof ConfigurableApplicationContext) { - ((ConfigurableApplicationContext) ctx).close(); + public void setFilterSecurityInterceptor( + FilterSecurityInterceptor filterSecurityInterceptor) { + this.filterSecurityInterceptor = filterSecurityInterceptor; + } + + public FilterSecurityInterceptor getFilterSecurityInterceptor() { + return filterSecurityInterceptor; + } + + public void setLoginFormUrl(String loginFormUrl) { + this.loginFormUrl = loginFormUrl; + } + + public String getLoginFormUrl() { + return loginFormUrl; + } + + public void afterPropertiesSet() throws Exception { + if ((loginFormUrl == null) || "".equals(loginFormUrl)) { + throw new IllegalArgumentException("loginFormUrl must be specified"); + } + + if (filterSecurityInterceptor == null) { + throw new IllegalArgumentException( + "filterSecurityInterceptor must be specified"); } } + public void destroy() {} + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (!(request instanceof HttpServletRequest)) { @@ -144,7 +145,7 @@ public class SecurityEnforcementFilter implements Filter { FilterInvocation fi = new FilterInvocation(request, response, chain); try { - securityInterceptor.invoke(fi); + filterSecurityInterceptor.invoke(fi); if (logger.isDebugEnabled()) { logger.debug("Chain processed normally"); @@ -174,49 +175,5 @@ public class SecurityEnforcementFilter implements Filter { } } - public void init(FilterConfig filterConfig) throws ServletException { - String appContextLocation = filterConfig.getInitParameter(CONFIG_LOCATION_PARAM); - - if ((appContextLocation != null) && (appContextLocation.length() > 0)) { - ourContext = true; - - if (Thread.currentThread().getContextClassLoader().getResource(appContextLocation) == null) { - throw new ServletException("Cannot locate " - + appContextLocation); - } - } - - loginFormUrl = filterConfig.getInitParameter("loginFormUrl"); - - if ((loginFormUrl == null) || "".equals(loginFormUrl)) { - throw new ServletException("loginFormUrl must be specified"); - } - - 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); - - if (beans.size() == 0) { - throw new ServletException( - "Bean context must contain at least one bean of type FilterSecurityInterceptor"); - } - - String beanName = (String) beans.keySet().iterator().next(); - securityInterceptor = (FilterSecurityInterceptor) beans.get(beanName); - } + public void init(FilterConfig filterConfig) throws ServletException {} } diff --git a/core/src/main/java/org/acegisecurity/ui/basicauth/BasicProcessingFilter.java b/core/src/main/java/org/acegisecurity/ui/basicauth/BasicProcessingFilter.java index 90c2d6d3d7..47b0c902f6 100644 --- a/core/src/main/java/org/acegisecurity/ui/basicauth/BasicProcessingFilter.java +++ b/core/src/main/java/org/acegisecurity/ui/basicauth/BasicProcessingFilter.java @@ -25,16 +25,10 @@ import org.apache.commons.codec.binary.Base64; 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 org.springframework.beans.factory.InitializingBean; import java.io.IOException; -import java.util.Map; - import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; @@ -87,63 +81,44 @@ import javax.servlet.http.HttpServletResponse; * sent with a request, it should return a 403 (forbidden) response.". *

* - *

- * 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 - * desirable 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 - * contextConfigLocation init param. + *

+ * Do not use this class directly. Instead configure + * web.xml to use the {@link + * net.sf.acegisecurity.util.FilterToBeanProxy}. *

- * - *

- * To use this filter, it is necessary to specify the following filter - * initialization parameters: - *

- * - *
    - *
  • - * contextConfigLocation (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. - *
  • - *
- * * * @author Ben Alex * @version $Id$ */ -public class BasicProcessingFilter implements Filter { +public class BasicProcessingFilter implements Filter, InitializingBean { //~ 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(BasicProcessingFilter.class); //~ Instance fields ======================================================== - private ApplicationContext ctx; private AuthenticationManager authenticationManager; - private boolean ourContext = false; //~ Methods ================================================================ - public void destroy() { - if (ourContext && ctx instanceof ConfigurableApplicationContext) { - ((ConfigurableApplicationContext) ctx).close(); + public void setAuthenticationManager( + AuthenticationManager authenticationManager) { + this.authenticationManager = authenticationManager; + } + + public AuthenticationManager getAuthenticationManager() { + return authenticationManager; + } + + public void afterPropertiesSet() throws Exception { + if (this.authenticationManager == null) { + throw new IllegalArgumentException( + "An AuthenticationManager is required"); } } + public void destroy() {} + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (!(request instanceof HttpServletRequest)) { @@ -208,42 +183,5 @@ public class BasicProcessingFilter implements Filter { chain.doFilter(request, response); } - public void init(FilterConfig filterConfig) throws ServletException { - String appContextLocation = filterConfig.getInitParameter(CONFIG_LOCATION_PARAM); - - if ((appContextLocation != null) && (appContextLocation.length() > 0)) { - ourContext = true; - - if (Thread.currentThread().getContextClassLoader().getResource(appContextLocation) == null) { - throw new ServletException("Cannot locate " - + 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); - - if (beans.size() == 0) { - throw new ServletException( - "Bean context must contain at least one bean of type AuthenticationManager"); - } - - String beanName = (String) beans.keySet().iterator().next(); - authenticationManager = (AuthenticationManager) beans.get(beanName); - } + public void init(FilterConfig arg0) throws ServletException {} } diff --git a/core/src/main/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilter.java b/core/src/main/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilter.java index c48db58c77..2d67b5cdcc 100644 --- a/core/src/main/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilter.java +++ b/core/src/main/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilter.java @@ -23,16 +23,10 @@ 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 org.springframework.beans.factory.InitializingBean; import java.io.IOException; -import java.util.Map; - import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; @@ -70,21 +64,7 @@ import javax.servlet.http.HttpServletResponse; *

* *

- * 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 - * desirable 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 - * contextConfigLocation init param. - *

- * - *

- * To use this filter, it is necessary to specify the following filter - * initialization parameters: + * To use this filter, it is necessary to specify the following properties: *

* *
    @@ -104,29 +84,21 @@ import javax.servlet.http.HttpServletResponse; * respond to. This parameter is optional, and defaults to * /j_acegi_security_check. * - *
  • - * contextConfigLocation (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. - *
  • *
* + *

+ * Do not use this class directly. Instead configure + * web.xml to use the {@link + * net.sf.acegisecurity.util.FilterToBeanProxy}. + *

* * @author Ben Alex * @author Colin Sampaleanu * @version $Id$ */ -public class AuthenticationProcessingFilter implements Filter { +public class AuthenticationProcessingFilter implements Filter, InitializingBean { //~ 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"; 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"; @@ -135,7 +107,6 @@ public class AuthenticationProcessingFilter implements Filter { //~ Instance fields ======================================================== - private ApplicationContext ctx; private AuthenticationManager authenticationManager; /** Where to redirect the browser to if authentication fails */ @@ -151,17 +122,68 @@ public class AuthenticationProcessingFilter implements Filter { * The URL destination that this filter intercepts and processes (usually * /j_acegi_security_check) */ - private String filterProcessesUrl; - private boolean ourContext = false; + private String filterProcessesUrl = "/j_acegi_security_check"; //~ Methods ================================================================ - public void destroy() { - if (ourContext && ctx instanceof ConfigurableApplicationContext) { - ((ConfigurableApplicationContext) ctx).close(); + public void setAuthenticationFailureUrl(String authenticationFailureUrl) { + this.authenticationFailureUrl = authenticationFailureUrl; + } + + public String getAuthenticationFailureUrl() { + return authenticationFailureUrl; + } + + public void setAuthenticationManager( + AuthenticationManager authenticationManager) { + this.authenticationManager = authenticationManager; + } + + public AuthenticationManager getAuthenticationManager() { + 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 { + if ((filterProcessesUrl == null) || "".equals(filterProcessesUrl)) { + throw new IllegalArgumentException( + "filterProcessesUrl must be specified"); + } + + if ((defaultTargetUrl == null) || "".equals(defaultTargetUrl)) { + throw new IllegalArgumentException( + "defaultTargetUrl must be specified"); + } + + if ((authenticationFailureUrl == null) + || "".equals(authenticationFailureUrl)) { + throw new IllegalArgumentException( + "authenticationFailureUrl must be specified"); + } + + if (authenticationManager == null) { + throw new IllegalArgumentException( + "authenticationManager must be specified"); } } + public void destroy() {} + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (!(request instanceof HttpServletRequest)) { @@ -245,63 +267,5 @@ public class AuthenticationProcessingFilter implements Filter { chain.doFilter(request, response); } - public void init(FilterConfig filterConfig) throws ServletException { - String appContextLocation = filterConfig.getInitParameter(CONFIG_LOCATION_PARAM); - - if ((appContextLocation != null) && (appContextLocation.length() > 0)) { - ourContext = true; - - if (Thread.currentThread().getContextClassLoader().getResource(appContextLocation) == null) { - throw new ServletException("Cannot locate " - + appContextLocation); - } - } - - defaultTargetUrl = filterConfig.getInitParameter("defaultTargetUrl"); - - if ((defaultTargetUrl == null) || "".equals(defaultTargetUrl)) { - throw new ServletException("defaultTargetUrl must be specified"); - } - - authenticationFailureUrl = filterConfig.getInitParameter( - "authenticationFailureUrl"); - - if ((authenticationFailureUrl == null) - || "".equals(authenticationFailureUrl)) { - throw new ServletException( - "authenticationFailureUrl must be specified"); - } - - filterProcessesUrl = filterConfig.getInitParameter("filterProcessesUrl"); - - if ((filterProcessesUrl == null) || "".equals(filterProcessesUrl)) { - filterProcessesUrl = "/j_acegi_security_check"; - } - - 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); - - if (beans.size() == 0) { - throw new ServletException( - "Bean context must contain at least one bean of type AuthenticationManager"); - } - - String beanName = (String) beans.keySet().iterator().next(); - authenticationManager = (AuthenticationManager) beans.get(beanName); - } + public void init(FilterConfig filterConfig) throws ServletException {} } diff --git a/core/src/main/java/org/acegisecurity/util/FilterToBeanProxy.java b/core/src/main/java/org/acegisecurity/util/FilterToBeanProxy.java new file mode 100644 index 0000000000..e4321df1ed --- /dev/null +++ b/core/src/main/java/org/acegisecurity/util/FilterToBeanProxy.java @@ -0,0 +1,164 @@ +/* Copyright 2004 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.util; + +import org.springframework.context.ApplicationContext; + +import org.springframework.web.context.support.WebApplicationContextUtils; + +import java.io.IOException; + +import java.util.Map; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; + + +/** + * Delegates Filter requests to a Spring-managed bean. + * + *

+ * This class acts as a proxy on behalf of a target Filter that is + * defined in the Spring bean context. It is necessary to specify which target + * Filter should be proxied as a filter initialization parameter. + *

+ * + *

+ * On filter initialisation, the class will use Spring's {@link + * WebApplicationContextUtils#getWebApplicationContext(ServletContext sc)} + * method to obtain an ApplicationContext instance. It will + * expect to find the target Filter in this + * ApplicationContext. + *

+ * + *

+ * To use this filter, it is necessary to specify the following filter + * initialization parameters: + *

+ * + *
    + *
  • + * targetClass indicates the class of the target + * Filter defined in the bean context. The only requirements are + * that this target class implements the javax.servlet.Filter + * interface and at least one instance is available in the + * ApplicationContext. + *
  • + *
  • + * targetBean (optional) indicates the bean name of the target + * class. This parameter should be specified if there is more than one bean in + * the ApplicationContext of the same type as defined by the + * targetClass parameter. + *
  • + *
+ * + * + * @author Ben Alex + * @version $Id$ + */ +public class FilterToBeanProxy implements Filter { + //~ Instance fields ======================================================== + + private Filter delegate; + + //~ Methods ================================================================ + + public void destroy() { + delegate.destroy(); + } + + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) throws IOException, ServletException { + delegate.doFilter(request, response, chain); + } + + public void init(FilterConfig filterConfig) throws ServletException { + String targetClassString = filterConfig.getInitParameter("targetClass"); + + if ((targetClassString == null) || "".equals(targetClassString)) { + throw new ServletException("targetClass must be specified"); + } + + Class targetClass; + + try { + targetClass = Thread.currentThread().getContextClassLoader() + .loadClass(targetClassString); + } catch (ClassNotFoundException ex) { + throw new ServletException("Class of type " + targetClassString + + " not found in classloader"); + } + + String targetBean = filterConfig.getInitParameter("targetBean"); + + if ("".equals(targetBean)) { + targetBean = null; + } + + ApplicationContext ctx = this.getContext(filterConfig); + + Map beans = ctx.getBeansOfType(targetClass, true, true); + + if (beans.size() == 0) { + throw new ServletException( + "Bean context must contain at least one bean of type " + + targetClassString); + } + + String beanName = null; + + if (targetBean == null) { + // Use first bean found + beanName = (String) beans.keySet().iterator().next(); + } else { + // Use the requested bean, providing it can be found + if (beans.containsKey(targetBean)) { + beanName = targetBean; + } else { + throw new ServletException("Bean with name '" + targetBean + + "' cannot be found in bean context"); + } + } + + Object object = beans.get(beanName); + + if (!(object instanceof Filter)) { + throw new ServletException("Bean '" + beanName + + "' does not implement javax.servlet.Filter"); + } + + delegate = (Filter) object; + + delegate.init(filterConfig); + } + + /** + * Allows test cases to override where application context obtained from. + * + * @param filterConfig which can be used to find the + * ServletContext + * + * @return the Spring application context + */ + protected ApplicationContext getContext(FilterConfig filterConfig) { + return WebApplicationContextUtils.getRequiredWebApplicationContext(filterConfig + .getServletContext()); + } +} diff --git a/core/src/main/java/org/acegisecurity/util/package.html b/core/src/main/java/org/acegisecurity/util/package.html new file mode 100644 index 0000000000..d845e7485f --- /dev/null +++ b/core/src/main/java/org/acegisecurity/util/package.html @@ -0,0 +1,5 @@ + + +General utility classes used throughout the Acegi Security System. + + diff --git a/core/src/test/java/org/acegisecurity/intercept/web/SecurityEnforcementFilterTests.java b/core/src/test/java/org/acegisecurity/intercept/web/SecurityEnforcementFilterTests.java index 0c4c3a258c..8427ac4d26 100644 --- a/core/src/test/java/org/acegisecurity/intercept/web/SecurityEnforcementFilterTests.java +++ b/core/src/test/java/org/acegisecurity/intercept/web/SecurityEnforcementFilterTests.java @@ -19,7 +19,6 @@ import junit.framework.TestCase; import net.sf.acegisecurity.AccessDeniedException; import net.sf.acegisecurity.BadCredentialsException; -import net.sf.acegisecurity.MockFilterConfig; import net.sf.acegisecurity.MockHttpServletRequest; import net.sf.acegisecurity.MockHttpServletResponse; import net.sf.acegisecurity.MockHttpSession; @@ -75,9 +74,11 @@ public class SecurityEnforcementFilterTests extends TestCase { false); // Test + SecurityEnforcementFilter filter = new SecurityEnforcementFilter(); + filter.setFilterSecurityInterceptor(interceptor); + filter.setLoginFormUrl("/login.jsp"); + MockHttpServletResponse response = new MockHttpServletResponse(); - SecurityEnforcementFilter filter = new MockSecurityEnforcementFilter(interceptor, - "/login.jsp"); filter.doFilter(request, response, chain); assertEquals(403, response.getError()); } @@ -108,6 +109,16 @@ public class SecurityEnforcementFilterTests extends TestCase { } } + public void testGettersSetters() { + SecurityEnforcementFilter filter = new SecurityEnforcementFilter(); + filter.setFilterSecurityInterceptor(new MockFilterSecurityInterceptor( + false, false)); + assertTrue(filter.getFilterSecurityInterceptor() != null); + + filter.setLoginFormUrl("/u"); + assertEquals("/u", filter.getLoginFormUrl()); + } + public void testRedirectedToLoginFormAndSessionShowsOriginalTargetWhenAuthenticationException() throws Exception { // Setup our HTTP request @@ -123,93 +134,42 @@ public class SecurityEnforcementFilterTests extends TestCase { true); // Test + SecurityEnforcementFilter filter = new SecurityEnforcementFilter(); + filter.setFilterSecurityInterceptor(interceptor); + filter.setLoginFormUrl("/login.jsp"); + filter.afterPropertiesSet(); + MockHttpServletResponse response = new MockHttpServletResponse(); - SecurityEnforcementFilter filter = new MockSecurityEnforcementFilter(interceptor, - "/login.jsp"); filter.doFilter(request, response, chain); assertEquals("/login.jsp", response.getRedirect()); assertEquals("/secure/page.html", request.getSession().getAttribute(AuthenticationProcessingFilter.ACEGI_SECURITY_TARGET_URL_KEY)); } - public void testStartupDetectsInvalidcontextConfigLocation() + public void testStartupDetectsMissingFilterSecurityInterceptor() throws Exception { - MockFilterConfig config = new MockFilterConfig(); - config.setInitParmeter("loginFormUrl", "/login.jsp"); - config.setInitParmeter("contextConfigLocation", - "net/sf/acegisecurity/intercept/web/securityfiltertest-invalid.xml"); - SecurityEnforcementFilter filter = new SecurityEnforcementFilter(); + filter.setLoginFormUrl("/login.jsp"); try { - filter.init(config); - fail("Should have thrown ServletException"); - } catch (ServletException expected) { - assertEquals("Bean context must contain at least one bean of type FilterSecurityInterceptor", + filter.afterPropertiesSet(); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertEquals("filterSecurityInterceptor must be specified", expected.getMessage()); } } - public void testStartupDetectsMissingAppContext() throws Exception { - MockFilterConfig config = new MockFilterConfig(); - config.setInitParmeter("loginFormUrl", "/login.jsp"); - - SecurityEnforcementFilter filter = new SecurityEnforcementFilter(); - - try { - filter.init(config); - fail("Should have thrown ServletException"); - } catch (ServletException expected) { - assertTrue(expected.getMessage().startsWith("Error obtaining/creating ApplicationContext for config.")); - } - - config.setInitParmeter("contextConfigLocation", ""); - - try { - filter.init(config); - fail("Should have thrown ServletException"); - } catch (ServletException expected) { - assertTrue(expected.getMessage().startsWith("Error obtaining/creating ApplicationContext for config.")); - } - } - - public void testStartupDetectsMissingInvalidcontextConfigLocation() - throws Exception { - MockFilterConfig config = new MockFilterConfig(); - config.setInitParmeter("loginFormUrl", "/login.jsp"); - config.setInitParmeter("contextConfigLocation", "DOES_NOT_EXIST"); - - SecurityEnforcementFilter filter = new SecurityEnforcementFilter(); - - try { - filter.init(config); - fail("Should have thrown ServletException"); - } catch (ServletException expected) { - assertTrue(expected.getMessage().startsWith("Cannot locate")); - } - } - public void testStartupDetectsMissingLoginFormUrl() throws Exception { - MockFilterConfig config = new MockFilterConfig(); - config.setInitParmeter("contextConfigLocation", - "net/sf/acegisecurity/intercept/web/securityfiltertest-valid.xml"); - SecurityEnforcementFilter filter = new SecurityEnforcementFilter(); + filter.setFilterSecurityInterceptor(new MockFilterSecurityInterceptor( + false, false)); try { - filter.init(config); - fail("Should have thrown ServletException"); - } catch (ServletException expected) { - assertEquals("loginFormUrl must be specified", expected.getMessage()); - } - - config.setInitParmeter("loginFormUrl", ""); - - try { - filter.init(config); - fail("Should have thrown ServletException"); - } catch (ServletException expected) { + filter.afterPropertiesSet(); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { assertEquals("loginFormUrl must be specified", expected.getMessage()); } } @@ -228,22 +188,19 @@ public class SecurityEnforcementFilterTests extends TestCase { false); // Test + SecurityEnforcementFilter filter = new SecurityEnforcementFilter(); + filter.setFilterSecurityInterceptor(interceptor); + filter.setLoginFormUrl("/login.jsp"); + MockHttpServletResponse response = new MockHttpServletResponse(); - SecurityEnforcementFilter filter = new MockSecurityEnforcementFilter(interceptor, - "/login.jsp"); filter.doFilter(request, response, chain); } public void testSuccessfulStartupAndShutdownDown() throws Exception { - MockFilterConfig config = new MockFilterConfig(); - config.setInitParmeter("contextConfigLocation", - "net/sf/acegisecurity/intercept/web/securityfiltertest-valid.xml"); - config.setInitParmeter("loginFormUrl", "/login.jsp"); - SecurityEnforcementFilter filter = new SecurityEnforcementFilter(); - filter.init(config); + filter.init(null); filter.destroy(); assertTrue(true); } @@ -298,17 +255,4 @@ public class SecurityEnforcementFilterTests extends TestCase { fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); } } - - private class MockSecurityEnforcementFilter - extends SecurityEnforcementFilter { - public MockSecurityEnforcementFilter( - FilterSecurityInterceptor securityInterceptor, String loginFormUrl) { - super.securityInterceptor = securityInterceptor; - super.loginFormUrl = loginFormUrl; - } - - private MockSecurityEnforcementFilter() { - super(); - } - } } diff --git a/core/src/test/java/org/acegisecurity/intercept/web/securityfiltertest-valid.xml b/core/src/test/java/org/acegisecurity/intercept/web/securityfiltertest-valid.xml deleted file mode 100644 index 60d1403380..0000000000 --- a/core/src/test/java/org/acegisecurity/intercept/web/securityfiltertest-valid.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - marissa=koala,ROLE_TELLER,ROLE_SUPERVISOR - dianne=emu,ROLE_TELLER - scott=wombat,ROLE_TELLER - peter=opal,disabled,ROLE_TELLER - - - - - - - - - - - - - - - - - - my_run_as_password - - - - - - false - - - - - - - - - - - - - - \A/secure/super.*\Z=ROLE_WE_DONT_HAVE - \A/secure/.*\Z=ROLE_SUPERVISOR,ROLE_TELLER - - - - - diff --git a/core/src/test/java/org/acegisecurity/ui/basicauth/BasicProcessingFilterTests.java b/core/src/test/java/org/acegisecurity/ui/basicauth/BasicProcessingFilterTests.java index e3f0e6b530..d61238e2c4 100644 --- a/core/src/test/java/org/acegisecurity/ui/basicauth/BasicProcessingFilterTests.java +++ b/core/src/test/java/org/acegisecurity/ui/basicauth/BasicProcessingFilterTests.java @@ -18,6 +18,7 @@ package net.sf.acegisecurity.ui.basicauth; import junit.framework.TestCase; import net.sf.acegisecurity.Authentication; +import net.sf.acegisecurity.MockAuthenticationManager; import net.sf.acegisecurity.MockFilterConfig; import net.sf.acegisecurity.MockHttpServletRequest; import net.sf.acegisecurity.MockHttpServletResponse; @@ -26,6 +27,9 @@ import net.sf.acegisecurity.ui.webapp.HttpSessionIntegrationFilter; import org.apache.commons.codec.binary.Base64; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + import java.io.IOException; import java.util.HashMap; @@ -102,23 +106,32 @@ public class BasicProcessingFilterTests extends TestCase { null, new MockHttpSession()); request.setServletPath("/some_file.html"); + // Launch an application context and access our bean + ApplicationContext ctx = new ClassPathXmlApplicationContext( + "net/sf/acegisecurity/ui/basicauth/filtertest-valid.xml"); + BasicProcessingFilter filter = (BasicProcessingFilter) ctx.getBean( + "basicProcessingFilter"); + // Setup our filter configuration MockFilterConfig config = new MockFilterConfig(); - config.setInitParmeter("contextConfigLocation", - "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); // Setup our expectation that the filter chain will be invoked MockFilterChain chain = new MockFilterChain(true); MockHttpServletResponse response = new MockHttpServletResponse(); // Test - BasicProcessingFilter filter = new BasicProcessingFilter(); executeFilterInContainerSimulator(config, filter, request, response, chain); assertTrue(request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY) == null); } + public void testGettersSetters() { + BasicProcessingFilter filter = new BasicProcessingFilter(); + filter.setAuthenticationManager(new MockAuthenticationManager()); + assertTrue(filter.getAuthenticationManager() != null); + } + public void testInvalidBasicAuthorizationTokenIsIgnored() throws Exception { // Setup our HTTP request @@ -131,17 +144,20 @@ public class BasicProcessingFilterTests extends TestCase { null, new MockHttpSession()); request.setServletPath("/some_file.html"); + // Launch an application context and access our bean + ApplicationContext ctx = new ClassPathXmlApplicationContext( + "net/sf/acegisecurity/ui/basicauth/filtertest-valid.xml"); + BasicProcessingFilter filter = (BasicProcessingFilter) ctx.getBean( + "basicProcessingFilter"); + // Setup our filter configuration MockFilterConfig config = new MockFilterConfig(); - config.setInitParmeter("contextConfigLocation", - "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); // Setup our expectation that the filter chain will be invoked MockFilterChain chain = new MockFilterChain(true); MockHttpServletResponse response = new MockHttpServletResponse(); // Test - BasicProcessingFilter filter = new BasicProcessingFilter(); executeFilterInContainerSimulator(config, filter, request, response, chain); @@ -159,17 +175,20 @@ public class BasicProcessingFilterTests extends TestCase { null, new MockHttpSession()); request.setServletPath("/some_file.html"); + // Launch an application context and access our bean + ApplicationContext ctx = new ClassPathXmlApplicationContext( + "net/sf/acegisecurity/ui/basicauth/filtertest-valid.xml"); + BasicProcessingFilter filter = (BasicProcessingFilter) ctx.getBean( + "basicProcessingFilter"); + // Setup our filter configuration MockFilterConfig config = new MockFilterConfig(); - config.setInitParmeter("contextConfigLocation", - "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); // Setup our expectation that the filter chain will be invoked MockFilterChain chain = new MockFilterChain(true); MockHttpServletResponse response = new MockHttpServletResponse(); // Test - BasicProcessingFilter filter = new BasicProcessingFilter(); executeFilterInContainerSimulator(config, filter, request, response, chain); @@ -189,77 +208,38 @@ public class BasicProcessingFilterTests extends TestCase { null, new MockHttpSession()); request.setServletPath("/some_file.html"); + // Launch an application context and access our bean + ApplicationContext ctx = new ClassPathXmlApplicationContext( + "net/sf/acegisecurity/ui/basicauth/filtertest-valid.xml"); + BasicProcessingFilter filter = (BasicProcessingFilter) ctx.getBean( + "basicProcessingFilter"); + // Setup our filter configuration MockFilterConfig config = new MockFilterConfig(); - config.setInitParmeter("contextConfigLocation", - "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); // Setup our expectation that the filter chain will be invoked MockFilterChain chain = new MockFilterChain(true); MockHttpServletResponse response = new MockHttpServletResponse(); // Test - BasicProcessingFilter filter = new BasicProcessingFilter(); executeFilterInContainerSimulator(config, filter, request, response, chain); assertTrue(request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY) == null); } - public void testStartupDetectsInvalidContextConfigLocation() + public void testStartupDetectsMissingAuthenticationManager() throws Exception { - MockFilterConfig config = new MockFilterConfig(); - config.setInitParmeter("contextConfigLocation", - "net/sf/acegisecurity/ui/webapp/filtertest-invalid.xml"); - - BasicProcessingFilter filter = new BasicProcessingFilter(); - try { - filter.init(config); - fail("Should have thrown ServletException"); - } catch (ServletException expected) { - assertEquals("Bean context must contain at least one bean of type AuthenticationManager", + BasicProcessingFilter filter = new BasicProcessingFilter(); + filter.afterPropertiesSet(); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertEquals("An AuthenticationManager is required", expected.getMessage()); } } - public void testStartupDetectsMissingAppContext() throws Exception { - MockFilterConfig config = new MockFilterConfig(); - - BasicProcessingFilter filter = new BasicProcessingFilter(); - - try { - filter.init(config); - fail("Should have thrown ServletException"); - } catch (ServletException expected) { - assertTrue(expected.getMessage().startsWith("Error obtaining/creating ApplicationContext for config.")); - } - - config.setInitParmeter("contextConfigLocation", ""); - - try { - filter.init(config); - fail("Should have thrown ServletException"); - } catch (ServletException expected) { - assertTrue(expected.getMessage().startsWith("Error obtaining/creating ApplicationContext for config.")); - } - } - - public void testStartupDetectsMissingInvalidContextConfigLocation() - throws Exception { - MockFilterConfig config = new MockFilterConfig(); - config.setInitParmeter("contextConfigLocation", "DOES_NOT_EXIST"); - - BasicProcessingFilter filter = new BasicProcessingFilter(); - - try { - filter.init(config); - fail("Should have thrown ServletException"); - } catch (ServletException expected) { - assertTrue(expected.getMessage().startsWith("Cannot locate")); - } - } - public void testSuccessLoginThenFailureLoginResultsInSessionLoosingToken() throws Exception { // Setup our HTTP request @@ -272,17 +252,20 @@ public class BasicProcessingFilterTests extends TestCase { null, new MockHttpSession()); request.setServletPath("/some_file.html"); + // Launch an application context and access our bean + ApplicationContext ctx = new ClassPathXmlApplicationContext( + "net/sf/acegisecurity/ui/basicauth/filtertest-valid.xml"); + BasicProcessingFilter filter = (BasicProcessingFilter) ctx.getBean( + "basicProcessingFilter"); + // Setup our filter configuration MockFilterConfig config = new MockFilterConfig(); - config.setInitParmeter("contextConfigLocation", - "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); // Setup our expectation that the filter chain will be invoked MockFilterChain chain = new MockFilterChain(true); MockHttpServletResponse response = new MockHttpServletResponse(); // Test - BasicProcessingFilter filter = new BasicProcessingFilter(); executeFilterInContainerSimulator(config, filter, request, response, chain); @@ -306,7 +289,6 @@ public class BasicProcessingFilterTests extends TestCase { response = new MockHttpServletResponse(); // Test - filter = new BasicProcessingFilter(); executeFilterInContainerSimulator(config, filter, request, response, chain); @@ -325,17 +307,20 @@ public class BasicProcessingFilterTests extends TestCase { null, new MockHttpSession()); request.setServletPath("/some_file.html"); + // Launch an application context and access our bean + ApplicationContext ctx = new ClassPathXmlApplicationContext( + "net/sf/acegisecurity/ui/basicauth/filtertest-valid.xml"); + BasicProcessingFilter filter = (BasicProcessingFilter) ctx.getBean( + "basicProcessingFilter"); + // Setup our filter configuration MockFilterConfig config = new MockFilterConfig(); - config.setInitParmeter("contextConfigLocation", - "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); // Setup our expectation that the filter chain will not be invoked, as we get a 403 forbidden response MockFilterChain chain = new MockFilterChain(false); MockHttpServletResponse response = new MockHttpServletResponse(); // Test - BasicProcessingFilter filter = new BasicProcessingFilter(); executeFilterInContainerSimulator(config, filter, request, response, chain); diff --git a/core/src/test/java/org/acegisecurity/ui/webapp/filtertest-invalid.xml b/core/src/test/java/org/acegisecurity/ui/basicauth/filtertest-valid.xml similarity index 60% rename from core/src/test/java/org/acegisecurity/ui/webapp/filtertest-invalid.xml rename to core/src/test/java/org/acegisecurity/ui/basicauth/filtertest-valid.xml index d2d53302fa..cc13218cfc 100644 --- a/core/src/test/java/org/acegisecurity/ui/webapp/filtertest-invalid.xml +++ b/core/src/test/java/org/acegisecurity/ui/basicauth/filtertest-valid.xml @@ -33,6 +33,22 @@ - + + + + + + + + + + + + + + + + + diff --git a/core/src/test/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilterTests.java b/core/src/test/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilterTests.java index 430998c6a2..1ec426bbc2 100644 --- a/core/src/test/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilterTests.java +++ b/core/src/test/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilterTests.java @@ -18,11 +18,15 @@ package net.sf.acegisecurity.ui.webapp; import junit.framework.TestCase; import net.sf.acegisecurity.Authentication; +import net.sf.acegisecurity.MockAuthenticationManager; import net.sf.acegisecurity.MockFilterConfig; import net.sf.acegisecurity.MockHttpServletRequest; import net.sf.acegisecurity.MockHttpServletResponse; import net.sf.acegisecurity.MockHttpSession; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + import java.io.IOException; import javax.servlet.Filter; @@ -100,19 +104,20 @@ public class AuthenticationProcessingFilterTests extends TestCase { "WRONG_PASSWORD"); request.setServletPath("/j_acegi_security_check"); + // Launch an application context and access our bean + ApplicationContext ctx = new ClassPathXmlApplicationContext( + "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); + AuthenticationProcessingFilter filter = (AuthenticationProcessingFilter) ctx + .getBean("authenticationProcessingFilter"); + // Setup our filter configuration MockFilterConfig config = new MockFilterConfig(); - config.setInitParmeter("contextConfigLocation", - "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); - config.setInitParmeter("defaultTargetUrl", "/"); - config.setInitParmeter("authenticationFailureUrl", "/failed.jsp"); // Setup our expectation that the filter chain will not be invoked, as we redirect to authenticationFailureUrl MockFilterChain chain = new MockFilterChain(false); MockHttpServletResponse response = new MockHttpServletResponse(); // Test - AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); executeFilterInContainerSimulator(config, filter, request, response, chain); System.out.println(response.getRedirect()); @@ -129,22 +134,25 @@ public class AuthenticationProcessingFilterTests extends TestCase { "marissa"); request.setParameter(AuthenticationProcessingFilter.ACEGI_SECURITY_FORM_PASSWORD_KEY, "koala"); - request.setServletPath("/j_my_security_check"); + request.setServletPath("/j_THIS_IS_MY_security_check"); + + // Launch an application context and access our bean + ApplicationContext ctx = new ClassPathXmlApplicationContext( + "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); + AuthenticationProcessingFilter filter = (AuthenticationProcessingFilter) ctx + .getBean("authenticationProcessingFilter"); + + // Must override the XML defined authenticationProcessesUrl + filter.setFilterProcessesUrl("/j_THIS_IS_MY_security_check"); // Setup our filter configuration MockFilterConfig config = new MockFilterConfig(); - config.setInitParmeter("contextConfigLocation", - "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); - config.setInitParmeter("defaultTargetUrl", "/"); - config.setInitParmeter("authenticationFailureUrl", "/failed.jsp"); - config.setInitParmeter("filterProcessesUrl", "/j_my_security_check"); // Setup our expectation that the filter chain will not be invoked, as we redirect to defaultTargetUrl MockFilterChain chain = new MockFilterChain(false); MockHttpServletResponse response = new MockHttpServletResponse(); // Test - AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); executeFilterInContainerSimulator(config, filter, request, response, chain); assertEquals("/", response.getRedirect()); @@ -154,6 +162,21 @@ public class AuthenticationProcessingFilterTests extends TestCase { .toString()); } + public void testGettersSetters() { + AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); + filter.setAuthenticationFailureUrl("/x"); + assertEquals("/x", filter.getAuthenticationFailureUrl()); + + filter.setAuthenticationManager(new MockAuthenticationManager()); + assertTrue(filter.getAuthenticationManager() != null); + + filter.setDefaultTargetUrl("/default"); + assertEquals("/default", filter.getDefaultTargetUrl()); + + filter.setFilterProcessesUrl("/p"); + assertEquals("/p", filter.getFilterProcessesUrl()); + } + public void testIgnoresAnyServletPathOtherThanFilterProcessesUrl() throws Exception { // Setup our HTTP request @@ -161,18 +184,19 @@ public class AuthenticationProcessingFilterTests extends TestCase { new MockHttpSession()); request.setServletPath("/j_some_other_url"); + // Launch an application context and access our bean + ApplicationContext ctx = new ClassPathXmlApplicationContext( + "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); + AuthenticationProcessingFilter filter = (AuthenticationProcessingFilter) ctx + .getBean("authenticationProcessingFilter"); + // Setup our filter configuration MockFilterConfig config = new MockFilterConfig(); - config.setInitParmeter("contextConfigLocation", - "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); - config.setInitParmeter("defaultTargetUrl", "/"); - config.setInitParmeter("authenticationFailureUrl", "/failed.jsp"); // Setup our expectation that the filter chain will be invoked, as should just proceed with chain MockFilterChain chain = new MockFilterChain(true); // Test - AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); executeFilterInContainerSimulator(config, filter, request, new MockHttpServletResponse(), chain); } @@ -188,19 +212,20 @@ public class AuthenticationProcessingFilterTests extends TestCase { "koala"); request.setServletPath("/j_acegi_security_check"); + // Launch an application context and access our bean + ApplicationContext ctx = new ClassPathXmlApplicationContext( + "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); + AuthenticationProcessingFilter filter = (AuthenticationProcessingFilter) ctx + .getBean("authenticationProcessingFilter"); + // Setup our filter configuration MockFilterConfig config = new MockFilterConfig(); - config.setInitParmeter("contextConfigLocation", - "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); - config.setInitParmeter("defaultTargetUrl", "/"); - config.setInitParmeter("authenticationFailureUrl", "/failed.jsp"); // Setup our expectation that the filter chain will not be invoked, as we redirect to defaultTargetUrl MockFilterChain chain = new MockFilterChain(false); MockHttpServletResponse response = new MockHttpServletResponse(); // Test - AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); executeFilterInContainerSimulator(config, filter, request, response, chain); assertEquals("/", response.getRedirect()); @@ -220,19 +245,20 @@ public class AuthenticationProcessingFilterTests extends TestCase { null); request.setServletPath("/j_acegi_security_check"); + // Launch an application context and access our bean + ApplicationContext ctx = new ClassPathXmlApplicationContext( + "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); + AuthenticationProcessingFilter filter = (AuthenticationProcessingFilter) ctx + .getBean("authenticationProcessingFilter"); + // Setup our filter configuration MockFilterConfig config = new MockFilterConfig(); - config.setInitParmeter("contextConfigLocation", - "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); - config.setInitParmeter("defaultTargetUrl", "/"); - config.setInitParmeter("authenticationFailureUrl", "/failed.jsp"); // Setup our expectation that the filter chain will not be invoked, as we redirect to defaultTargetUrl MockFilterChain chain = new MockFilterChain(false); MockHttpServletResponse response = new MockHttpServletResponse(); // Test - AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); executeFilterInContainerSimulator(config, filter, request, response, chain); assertEquals("/failed.jsp", response.getRedirect()); @@ -249,138 +275,88 @@ public class AuthenticationProcessingFilterTests extends TestCase { "koala"); request.setServletPath("/j_acegi_security_check"); + // Launch an application context and access our bean + ApplicationContext ctx = new ClassPathXmlApplicationContext( + "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); + AuthenticationProcessingFilter filter = (AuthenticationProcessingFilter) ctx + .getBean("authenticationProcessingFilter"); + // Setup our filter configuration MockFilterConfig config = new MockFilterConfig(); - config.setInitParmeter("contextConfigLocation", - "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); - config.setInitParmeter("defaultTargetUrl", "/"); - config.setInitParmeter("authenticationFailureUrl", "/failed.jsp"); // Setup our expectation that the filter chain will not be invoked, as we redirect to defaultTargetUrl MockFilterChain chain = new MockFilterChain(false); MockHttpServletResponse response = new MockHttpServletResponse(); // Test - AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); executeFilterInContainerSimulator(config, filter, request, response, chain); assertEquals("/failed.jsp", response.getRedirect()); assertTrue(request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY) == null); } - public void testStartupDetectsInvalidcontextConfigLocation() + public void testStartupDetectsInvalidAuthenticationFailureUrl() throws Exception { - MockFilterConfig config = new MockFilterConfig(); - config.setInitParmeter("defaultTargetUrl", "/"); - config.setInitParmeter("authenticationFailureUrl", "/failed.jsp"); - config.setInitParmeter("contextConfigLocation", - "net/sf/acegisecurity/ui/webapp/filtertest-invalid.xml"); - AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); + filter.setAuthenticationManager(new MockAuthenticationManager()); + filter.setDefaultTargetUrl("/"); + filter.setFilterProcessesUrl("/j_acegi_security_check"); try { - filter.init(config); - fail("Should have thrown ServletException"); - } catch (ServletException expected) { - assertEquals("Bean context must contain at least one bean of type AuthenticationManager", - expected.getMessage()); - } - } - - public void testStartupDetectsMissingAppContext() throws Exception { - MockFilterConfig config = new MockFilterConfig(); - config.setInitParmeter("defaultTargetUrl", "/"); - config.setInitParmeter("authenticationFailureUrl", "/failed.jsp"); - - AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); - - try { - filter.init(config); - fail("Should have thrown ServletException"); - } catch (ServletException expected) { - assertTrue(expected.getMessage().startsWith("Error obtaining/creating ApplicationContext for config.")); - } - - config.setInitParmeter("contextConfigLocation", ""); - - try { - filter.init(config); - fail("Should have thrown ServletException"); - } catch (ServletException expected) { - assertTrue(expected.getMessage().startsWith("Error obtaining/creating ApplicationContext for config.")); - } - } - - public void testStartupDetectsMissingAuthenticationFailureUrl() - throws Exception { - MockFilterConfig config = new MockFilterConfig(); - config.setInitParmeter("contextConfigLocation", - "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); - config.setInitParmeter("defaultTargetUrl", "/"); - - AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); - - try { - filter.init(config); - fail("Should have thrown ServletException"); - } catch (ServletException expected) { - assertEquals("authenticationFailureUrl must be specified", - expected.getMessage()); - } - - config.setInitParmeter("authenticationFailureUrl", ""); - - try { - filter.init(config); - fail("Should have thrown ServletException"); - } catch (ServletException expected) { + filter.afterPropertiesSet(); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { assertEquals("authenticationFailureUrl must be specified", expected.getMessage()); } } - public void testStartupDetectsMissingDefaultTargetUrl() + public void testStartupDetectsInvalidAuthenticationManager() throws Exception { - MockFilterConfig config = new MockFilterConfig(); - config.setInitParmeter("authenticationFailureUrl", "/failed.jsp"); - config.setInitParmeter("contextConfigLocation", - "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); - AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); + filter.setAuthenticationFailureUrl("/failed.jsp"); + filter.setDefaultTargetUrl("/"); + filter.setFilterProcessesUrl("/j_acegi_security_check"); try { - filter.init(config); - fail("Should have thrown ServletException"); - } catch (ServletException expected) { - assertEquals("defaultTargetUrl must be specified", + filter.afterPropertiesSet(); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertEquals("authenticationManager must be specified", expected.getMessage()); } + } - config.setInitParmeter("defaultTargetUrl", ""); + public void testStartupDetectsInvalidDefaultTargetUrl() + throws Exception { + AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); + filter.setAuthenticationFailureUrl("/failed.jsp"); + filter.setAuthenticationManager(new MockAuthenticationManager()); + filter.setFilterProcessesUrl("/j_acegi_security_check"); try { - filter.init(config); - fail("Should have thrown ServletException"); - } catch (ServletException expected) { + filter.afterPropertiesSet(); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { assertEquals("defaultTargetUrl must be specified", expected.getMessage()); } } - public void testStartupDetectsMissingInvalidcontextConfigLocation() + public void testStartupDetectsInvalidFilterProcessesUrl() throws Exception { - MockFilterConfig config = new MockFilterConfig(); - config.setInitParmeter("defaultTargetUrl", "/"); - config.setInitParmeter("authenticationFailureUrl", "/failed.jsp"); - config.setInitParmeter("contextConfigLocation", "DOES_NOT_EXIST"); - AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); + filter.setAuthenticationFailureUrl("/failed.jsp"); + filter.setAuthenticationManager(new MockAuthenticationManager()); + filter.setDefaultTargetUrl("/"); + filter.setFilterProcessesUrl(null); try { - filter.init(config); - fail("Should have thrown ServletException"); - } catch (ServletException expected) { - assertTrue(expected.getMessage().startsWith("Cannot locate")); + filter.afterPropertiesSet(); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertEquals("filterProcessesUrl must be specified", + expected.getMessage()); } } @@ -395,19 +371,20 @@ public class AuthenticationProcessingFilterTests extends TestCase { "koala"); request.setServletPath("/j_acegi_security_check"); + // Launch an application context and access our bean + ApplicationContext ctx = new ClassPathXmlApplicationContext( + "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); + AuthenticationProcessingFilter filter = (AuthenticationProcessingFilter) ctx + .getBean("authenticationProcessingFilter"); + // Setup our filter configuration MockFilterConfig config = new MockFilterConfig(); - config.setInitParmeter("contextConfigLocation", - "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); - config.setInitParmeter("defaultTargetUrl", "/"); - config.setInitParmeter("authenticationFailureUrl", "/failed.jsp"); // Setup our expectation that the filter chain will not be invoked, as we redirect to authenticationFailureUrl MockFilterChain chain = new MockFilterChain(false); MockHttpServletResponse response = new MockHttpServletResponse(); // Test - AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); executeFilterInContainerSimulator(config, filter, request, response, chain); assertEquals("/", response.getRedirect()); @@ -440,19 +417,20 @@ public class AuthenticationProcessingFilterTests extends TestCase { request.getSession().setAttribute(AuthenticationProcessingFilter.ACEGI_SECURITY_TARGET_URL_KEY, "/my-destination"); + // Launch an application context and access our bean + ApplicationContext ctx = new ClassPathXmlApplicationContext( + "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); + AuthenticationProcessingFilter filter = (AuthenticationProcessingFilter) ctx + .getBean("authenticationProcessingFilter"); + // Setup our filter configuration MockFilterConfig config = new MockFilterConfig(); - config.setInitParmeter("contextConfigLocation", - "net/sf/acegisecurity/ui/webapp/filtertest-valid.xml"); - config.setInitParmeter("defaultTargetUrl", "/"); - config.setInitParmeter("authenticationFailureUrl", "/failed.jsp"); // Setup our expectation that the filter chain will not be invoked, as we redirect to defaultTargetUrl MockFilterChain chain = new MockFilterChain(false); MockHttpServletResponse response = new MockHttpServletResponse(); // Test - AuthenticationProcessingFilter filter = new AuthenticationProcessingFilter(); executeFilterInContainerSimulator(config, filter, request, response, chain); assertEquals("/my-destination", response.getRedirect()); diff --git a/core/src/test/java/org/acegisecurity/ui/webapp/filtertest-valid.xml b/core/src/test/java/org/acegisecurity/ui/webapp/filtertest-valid.xml index 38a23ee9ca..a13d85cd8b 100644 --- a/core/src/test/java/org/acegisecurity/ui/webapp/filtertest-valid.xml +++ b/core/src/test/java/org/acegisecurity/ui/webapp/filtertest-valid.xml @@ -47,4 +47,11 @@ + + + /failed.jsp + / + /j_acegi_security_check + + diff --git a/core/src/test/java/org/acegisecurity/util/FilterToBeanProxyTests.java b/core/src/test/java/org/acegisecurity/util/FilterToBeanProxyTests.java new file mode 100644 index 0000000000..6dab01e474 --- /dev/null +++ b/core/src/test/java/org/acegisecurity/util/FilterToBeanProxyTests.java @@ -0,0 +1,260 @@ +/* Copyright 2004 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.util; + +import junit.framework.TestCase; + +import net.sf.acegisecurity.MockFilterConfig; +import net.sf.acegisecurity.MockHttpServletRequest; +import net.sf.acegisecurity.MockHttpServletResponse; + +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +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; + + +/** + * Tests {@link FilterToBeanProxy}. + * + * @author Ben Alex + * @version $Id$ + */ +public class FilterToBeanProxyTests extends TestCase { + //~ Constructors =========================================================== + + public FilterToBeanProxyTests() { + super(); + } + + public FilterToBeanProxyTests(String arg0) { + super(arg0); + } + + //~ Methods ================================================================ + + public final void setUp() throws Exception { + super.setUp(); + } + + public static void main(String[] args) { + junit.textui.TestRunner.run(FilterToBeanProxyTests.class); + } + + public void testDetectsClassNotInClassLoader() throws Exception { + // Setup our filter + MockFilterConfig config = new MockFilterConfig(); + config.setInitParmeter("targetClass", "net.sf.DOES.NOT.EXIST"); + + FilterToBeanProxy filter = new MockFilterToBeanProxy( + "net/sf/acegisecurity/util/filtertest-valid.xml"); + + try { + filter.init(config); + fail("Should have thrown ServletException"); + } catch (ServletException expected) { + assertEquals("Class of type net.sf.DOES.NOT.EXIST not found in classloader", + expected.getMessage()); + } + } + + public void testDetectsMissingTargetClass() throws Exception { + // Setup our filter + MockFilterConfig config = new MockFilterConfig(); + config.setInitParmeter("targetBean", "mockFilter"); + + FilterToBeanProxy filter = new MockFilterToBeanProxy( + "net/sf/acegisecurity/util/filtertest-valid.xml"); + + try { + filter.init(config); + fail("Should have thrown ServletException"); + } catch (ServletException expected) { + assertEquals("targetClass must be specified", expected.getMessage()); + } + } + + public void testDetectsTargetBeanIsNotAFilter() throws Exception { + // Setup our filter + MockFilterConfig config = new MockFilterConfig(); + config.setInitParmeter("targetClass", + "net.sf.acegisecurity.util.MockNotAFilter"); + + FilterToBeanProxy filter = new MockFilterToBeanProxy( + "net/sf/acegisecurity/util/filtertest-valid.xml"); + + try { + filter.init(config); + fail("Should have thrown ServletException"); + } catch (ServletException expected) { + assertEquals("Bean 'mockNotAFilter' does not implement javax.servlet.Filter", + expected.getMessage()); + } + } + + public void testDetectsTargetBeanNotInBeanContext() + throws Exception { + // Setup our filter + MockFilterConfig config = new MockFilterConfig(); + config.setInitParmeter("targetClass", + "net.sf.acegisecurity.util.MockFilter"); + config.setInitParmeter("targetBean", "WRONG_NAME"); + + FilterToBeanProxy filter = new MockFilterToBeanProxy( + "net/sf/acegisecurity/util/filtertest-valid.xml"); + + try { + filter.init(config); + fail("Should have thrown ServletException"); + } catch (ServletException expected) { + assertEquals("Bean with name 'WRONG_NAME' cannot be found in bean context", + expected.getMessage()); + } + } + + public void testDetectsTargetClassNotInBeanContext() + throws Exception { + // Setup our filter + MockFilterConfig config = new MockFilterConfig(); + config.setInitParmeter("targetClass", + "net.sf.acegisecurity.util.FilterToBeanProxyTests"); + + FilterToBeanProxy filter = new MockFilterToBeanProxy( + "net/sf/acegisecurity/util/filtertest-valid.xml"); + + try { + filter.init(config); + fail("Should have thrown ServletException"); + } catch (ServletException expected) { + assertEquals("Bean context must contain at least one bean of type net.sf.acegisecurity.util.FilterToBeanProxyTests", + expected.getMessage()); + } + } + + public void testIgnoresEmptyTargetBean() throws Exception { + // Setup our filter + MockFilterConfig config = new MockFilterConfig(); + config.setInitParmeter("targetClass", + "net.sf.acegisecurity.util.MockFilter"); + config.setInitParmeter("targetBean", ""); + + // Setup our expectation that the filter chain will be invoked + MockFilterChain chain = new MockFilterChain(true); + + MockHttpServletResponse response = new MockHttpServletResponse(); + MockHttpServletRequest request = new MockHttpServletRequest("/go"); + + FilterToBeanProxy filter = new MockFilterToBeanProxy( + "net/sf/acegisecurity/util/filtertest-valid.xml"); + + executeFilterInContainerSimulator(config, filter, request, response, + chain); + } + + public void testNormalOperationWithDefault() throws Exception { + // Setup our filter + MockFilterConfig config = new MockFilterConfig(); + config.setInitParmeter("targetClass", + "net.sf.acegisecurity.util.MockFilter"); + + // Setup our expectation that the filter chain will be invoked + MockFilterChain chain = new MockFilterChain(true); + + MockHttpServletResponse response = new MockHttpServletResponse(); + MockHttpServletRequest request = new MockHttpServletRequest("/go"); + + FilterToBeanProxy filter = new MockFilterToBeanProxy( + "net/sf/acegisecurity/util/filtertest-valid.xml"); + + executeFilterInContainerSimulator(config, filter, request, response, + chain); + } + + public void testNormalOperationWithSpecificBeanName() + throws Exception { + // Setup our filter + MockFilterConfig config = new MockFilterConfig(); + config.setInitParmeter("targetClass", + "net.sf.acegisecurity.util.MockFilter"); + config.setInitParmeter("targetBean", "mockFilter"); + + // Setup our expectation that the filter chain will be invoked + MockFilterChain chain = new MockFilterChain(true); + + MockHttpServletResponse response = new MockHttpServletResponse(); + MockHttpServletRequest request = new MockHttpServletRequest("/go"); + + FilterToBeanProxy filter = new MockFilterToBeanProxy( + "net/sf/acegisecurity/util/filtertest-valid.xml"); + + executeFilterInContainerSimulator(config, filter, request, response, + chain); + } + + private void executeFilterInContainerSimulator(FilterConfig filterConfig, + Filter filter, ServletRequest request, ServletResponse response, + FilterChain filterChain) throws ServletException, IOException { + filter.init(filterConfig); + filter.doFilter(request, response, filterChain); + filter.destroy(); + } + + //~ Inner Classes ========================================================== + + private class MockFilterChain implements FilterChain { + private boolean expectToProceed; + + public MockFilterChain(boolean expectToProceed) { + this.expectToProceed = expectToProceed; + } + + private MockFilterChain() { + super(); + } + + public void doFilter(ServletRequest request, ServletResponse response) + throws IOException, ServletException { + if (expectToProceed) { + assertTrue(true); + } else { + fail("Did not expect filter chain to proceed"); + } + } + } + + private class MockFilterToBeanProxy extends FilterToBeanProxy { + private String appContextLocation; + + public MockFilterToBeanProxy(String appContextLocation) { + this.appContextLocation = appContextLocation; + } + + private MockFilterToBeanProxy() { + super(); + } + + protected ApplicationContext getContext(FilterConfig filterConfig) { + return new ClassPathXmlApplicationContext(appContextLocation); + } + } +} diff --git a/core/src/test/java/org/acegisecurity/util/MockFilter.java b/core/src/test/java/org/acegisecurity/util/MockFilter.java new file mode 100644 index 0000000000..8a25614254 --- /dev/null +++ b/core/src/test/java/org/acegisecurity/util/MockFilter.java @@ -0,0 +1,45 @@ +/* Copyright 2004 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.util; + +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; + + +/** + * A simple filter that the test case can delegate to. + * + * @author Ben Alex + * @version $Id$ + */ +public class MockFilter implements Filter { + //~ Methods ================================================================ + + public void destroy() {} + + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) throws IOException, ServletException { + chain.doFilter(request, response); + } + + public void init(FilterConfig config) throws ServletException {} +} diff --git a/core/src/test/java/org/acegisecurity/util/MockNotAFilter.java b/core/src/test/java/org/acegisecurity/util/MockNotAFilter.java new file mode 100644 index 0000000000..338ae5dc49 --- /dev/null +++ b/core/src/test/java/org/acegisecurity/util/MockNotAFilter.java @@ -0,0 +1,24 @@ +/* Copyright 2004 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.util; + +/** + * A class that is not a filter. + * + * @author Ben Alex + * @version $Id$ + */ +public class MockNotAFilter {} diff --git a/core/src/test/java/org/acegisecurity/intercept/web/securityfiltertest-invalid.xml b/core/src/test/java/org/acegisecurity/util/filtertest-valid.xml similarity index 67% rename from core/src/test/java/org/acegisecurity/intercept/web/securityfiltertest-invalid.xml rename to core/src/test/java/org/acegisecurity/util/filtertest-valid.xml index 6409f0e4d0..78c34b76e4 100644 --- a/core/src/test/java/org/acegisecurity/intercept/web/securityfiltertest-invalid.xml +++ b/core/src/test/java/org/acegisecurity/util/filtertest-valid.xml @@ -21,17 +21,7 @@ - - - - marissa=koala,ROLE_TELLER,ROLE_SUPERVISOR - dianne=emu,ROLE_TELLER - scott=wombat,ROLE_TELLER - peter=opal,disabled,ROLE_TELLER - - - - - + + diff --git a/docs/reference/src/index.xml b/docs/reference/src/index.xml index 3087af5f5f..7412e24e9f 100644 --- a/docs/reference/src/index.xml +++ b/docs/reference/src/index.xml @@ -503,14 +503,14 @@ FilterInvocation Security Interceptor To secure FilterInvocations, developers need - to add a SecurityEnforcementFilter to their - web.xml. A typical configuration example is - provided below: <filter> + to add a filter to their web.xml that delegates to + the SecurityEnforcementFilter. A typical + configuration example is provided below: <filter> <filter-name>Acegi HTTP Request Security Filter</filter-name> - <filter-class>net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter</filter-class> + <filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class> <init-param> - <param-name>loginFormUrl</param-name> - <param-value>/acegilogin.jsp</param-value> + <param-name>targetClass</param-name> + <param-value>net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter</param-value> </init-param> </filter> @@ -519,34 +519,36 @@ <url-pattern>/*</url-pattern> </filter-mapping> - The loginFormUrl is where the filter will - redirect the user's browser if they request a secure HTTP resource but - they are not authenticated. If the user is authenticated, a "403 - Forbidden" response will be returned to the browser. All paths are - relative to the web application root. + Notice that the filter is actually a + FilterToBeanProxy. Most of the filters used by the + Acegi Security System for Spring use this class . What it does is + delegate the Filter's methods through to a bean + which is obtained from the Spring application context. This enables + the bean to benefit from the Spring application context lifecycle + support and configuration flexibility. The + FilterToBeanProxy only requires a single + initialization parameter, targetClass, which will + be used to identify the bean in the application context. In the + unlikely event there is more than one bean in the application context + that matches this class, the targetBean + initialization parameter should be used. This parameter simply + represents the name of the bean in the application context. Like + standard Spring web applications, the + FilterToBeanProxy accesses the application context + via + WebApplicationContextUtils.getWebApplicationContext(ServletContext), + so you should configure a ContextLoaderListener in + web.xml. - To perform its function, the - SecurityEnforcementFilter will need to delegate to - a properly configured FilterSecurityInterceptor. To - do this it requires access to a Spring application context, which is - usually obtained from - WebApplicationContextUtils.getWebApplicationContext(ServletContext). - This is usually made available by using Spring's - ContextLoaderListener in - web.xml. Alternatively, the - web.xml can be used to define a filter - <init-param> named - contextConfigLocation. This initialization - parameter will represent a path to a Spring XML application context - that the SecurityEnforcementFilter will load during - startup. + In the application context you will need to configure two + beans: - The configuration of the - FilterSecurityInterceptor in the Spring application - context is very similar to the - MethodSecurityInterceptor: + <bean id="securityEnforcementFilter" class="net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter"> + <property name="filterSecurityInterceptor"><ref bean="filterInvocationInterceptor"/></property> + <property name="loginFormUrl"><value>/acegilogin.jsp</value></property> +</bean> - <bean id="filterInvocationInterceptor" class="net.sf.acegisecurity.intercept.web.FilterSecurityInterceptor"> +<bean id="filterInvocationInterceptor" class="net.sf.acegisecurity.intercept.web.FilterSecurityInterceptor"> <property name="authenticationManager"><ref bean="authenticationManager"/></property> <property name="accessDecisionManager"><ref bean="accessDecisionManager"/></property> <property name="runAsManager"><ref bean="runAsManager"/></property> @@ -557,7 +559,18 @@ \A/secure/.*\Z=ROLE_SUPERVISOR,ROLE_TELLER </value> </property> -</bean> +</bean> + + The loginFormUrl is where the filter will + redirect the user's browser if they request a secure HTTP resource but + they are not authenticated. If the user is authenticated, a "403 + Forbidden" response will be returned to the browser. All paths are + relative to the web application root. + + The SecurityEnforcementFilter primarily + provides redirection and session management support. It delegates + actual FilterInvocation security decisions to the + configured FilterSecurityInterceptor. Like any other security interceptor, the FilterSecurityInterceptor requires a reference to @@ -1483,22 +1496,15 @@ public boolean supports(Class clazz); j_password input fields, and posts to a URL that is monitored by the filter (by default j_acegi_security_check). The filter is defined in - web.xml as follows: + web.xml behind a + FilterToBeanProxy as follows: <filter> <filter-name>Acegi Authentication Processing Filter</filter-name> - <filter-class>net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter</filter-class> + <filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class> <init-param> - <param-name>authenticationFailureUrl</param-name> - <param-value>/acegilogin.jsp?login_error=1</param-value> - </init-param> - <init-param> - <param-name>defaultTargetUrl</param-name> - <param-value>/</param-value> - </init-param> - <init-param> - <param-name>filterProcessUrl</param-name> - <param-value>/j_acegi_security_check</param-value> + <param-name>targetClass</param-name> + <param-value>net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter</param-value> </init-param> </filter> @@ -1507,25 +1513,22 @@ public boolean supports(Class clazz); <url-pattern>/*</url-pattern> </filter-mapping> - To perform its function, the - AuthenticationProcessingFilter will need to - delegate to a properly configured - AuthenticationManager. To do this it requires - access to a Spring application context, which is usually obtained from - WebApplicationContextUtils.getWebApplicationContext(ServletContext). - This is usually made available by using Spring's - ContextLoaderListener in - web.xml. Alternatively, the - web.xml can be used to define a filter - <init-param> named - contextConfigLocation. This initialization - parameter will represent a path to a Spring XML application context - that the AuthenticationProcessingFilter will load - during startup. + For a discussion of FilterToBeanProxy, please + refer to the FilterInvocation Security Interceptor section. The + application context will need to define the + AuthenticationProcessingFilter: - The AuthenticationManager processes each - authentication request. If authentication fails, the browser will be - redirected to the authenticationFailureUrl. The + <bean id="authenticationProcessingFilter" class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter"> + <property name="authenticationManager"><ref bean="authenticationManager"/></property> + <property name="authenticationFailureUrl"><value>/acegilogin.jsp?login_error=1</value></property> + <property name="defaultTargetUrl"><value>/</value></property> + <property name="filterProcessesUrl"><value>/j_acegi_security_check</value></property> +</bean> + + The configured AuthenticationManager + processes each authentication request. If authentication fails, the + browser will be redirected to the + authenticationFailureUrl. The AuthenticationException will be placed into the HttpSession attribute indicated by AuthenticationProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY, @@ -1549,8 +1552,7 @@ public boolean supports(Class clazz); is completed the user can return to what they were trying to access. If for some reason the HttpSession does not indicate the target URL, the browser will be redirected to the - defaultTargetUrl filter initialization - property. + defaultTargetUrl property. Because this authentication approach is fully contained within a single web application, HTTP Session Authentication is recommended to @@ -1567,13 +1569,20 @@ public boolean supports(Class clazz); standard authentication of web browser users, we recommend HTTP Session Authentication). The standard governing HTTP Basic Authentication is defined by RFC 1945, Section 11, and the - BasicProcessingFilter conforms with this RFC. To - implement HTTP Basic Authentication, it is necessary to add the - following filter to web.xml: + BasicProcessingFilter conforms with this RFC. + + + To implement HTTP Basic Authentication, it is necessary to add + the following filter to web.xml, behind a + FilterToBeanProxy: <filter> <filter-name>Acegi HTTP BASIC Authorization Filter</filter-name> - <filter-class>net.sf.acegisecurity.ui.basicauth.BasicProcessingFilter</filter-class> + <filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class> + <init-param> + <param-name>targetClass</param-name> + <param-value>net.sf.acegisecurity.ui.basicauth.BasicProcessingFilter</param-value> + </init-param> </filter> <filter-mapping> @@ -1581,26 +1590,19 @@ public boolean supports(Class clazz); <url-pattern>/*</url-pattern> </filter-mapping> - Like the AuthenticationProcessingFilter - discussed above, the BasicProcessingFilter will - need to delegate to a properly configured - AuthenticationManager. To do this it requires - access to a Spring application context, which is usually obtained from - WebApplicationContextUtils.getWebApplicationContext(ServletContext). - This is usually made available by using Spring's - ContextLoaderListener in - web.xml. Alternatively, the - web.xml can be used to define a filter - <init-param> named - contextConfigLocation. This initialization - parameter will represent a path to a Spring XML application context - that the AuthenticationProcessingFilter will load - during startup. + For a discussion of FilterToBeanProxy, please + refer to the FilterInvocation Security Interceptor section. The + application context will need to define the + BasicProcessingFilter: - The AuthenticationManager processes each - authentication request. If authentication fails, a 403 (forbidden) - response will be returned in response to the HTTP request. If - authentication is successful, the resulting + <bean id="basicProcessingFilter" class="net.sf.acegisecurity.ui.basicauth.BasicProcessingFilter"> + <property name="authenticationManager"><ref bean="authenticationManager"/></property> +</bean> + + The configured AuthenticationManager + processes each authentication request. If authentication fails, a 403 + (forbidden) response will be returned in response to the HTTP request. + If authentication is successful, the resulting Authentication object will be placed into the HttpSession attribute indicated by HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY. diff --git a/samples/contacts/etc/ca/applicationContext.xml b/samples/contacts/etc/ca/applicationContext.xml index b0189b1762..b785c9c100 100644 --- a/samples/contacts/etc/ca/applicationContext.xml +++ b/samples/contacts/etc/ca/applicationContext.xml @@ -50,6 +50,10 @@ + + + + diff --git a/samples/contacts/etc/ca/web.xml b/samples/contacts/etc/ca/web.xml index 4b1d1652c2..4bc7ff1dc6 100644 --- a/samples/contacts/etc/ca/web.xml +++ b/samples/contacts/etc/ca/web.xml @@ -26,7 +26,11 @@ Acegi HTTP BASIC Authorization Filter - net.sf.acegisecurity.ui.basicauth.BasicProcessingFilter + net.sf.acegisecurity.util.FilterToBeanProxy + + targetClass + net.sf.acegisecurity.ui.basicauth.BasicProcessingFilter + diff --git a/samples/contacts/etc/filter/applicationContext.xml b/samples/contacts/etc/filter/applicationContext.xml index 75365c16b8..213241f855 100644 --- a/samples/contacts/etc/filter/applicationContext.xml +++ b/samples/contacts/etc/filter/applicationContext.xml @@ -45,6 +45,10 @@ + + + + @@ -125,6 +129,18 @@ + + + /acegilogin.jsp?login_error=1 + / + /j_acegi_security_check + + + + + /acegilogin.jsp + + false @@ -134,11 +150,9 @@ - - diff --git a/samples/contacts/etc/filter/web-filters-acegisecurity.xml b/samples/contacts/etc/filter/web-filters-acegisecurity.xml deleted file mode 100644 index 7a6b8bc63f..0000000000 --- a/samples/contacts/etc/filter/web-filters-acegisecurity.xml +++ /dev/null @@ -1,112 +0,0 @@ - - - - - - - - - - - - - marissa=koala,ROLE_TELLER,ROLE_SUPERVISOR - dianne=emu,ROLE_TELLER - scott=wombat,ROLE_TELLER - peter=opal,disabled,ROLE_TELLER - - - - - - - - - - - - - - - - - - - - - - my_run_as_password - - - - - - false - - - - - - - - - - - - - - - - CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON - \A/secure/super.*\Z=ROLE_WE_DONT_HAVE - \A/secure/.*\Z=ROLE_SUPERVISOR,ROLE_TELLER - - - - - - - diff --git a/samples/contacts/etc/filter/web.xml b/samples/contacts/etc/filter/web.xml index 5baa0042e0..df4ef191cc 100644 --- a/samples/contacts/etc/filter/web.xml +++ b/samples/contacts/etc/filter/web.xml @@ -26,24 +26,20 @@ Acegi Authentication Processing Filter - net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter + net.sf.acegisecurity.util.FilterToBeanProxy - authenticationFailureUrl - /acegilogin.jsp?login_error=1 - - - defaultTargetUrl - / - - - filterProcessUrl - /j_acegi_security_check + targetClass + net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter Acegi HTTP BASIC Authorization Filter - net.sf.acegisecurity.ui.basicauth.BasicProcessingFilter + net.sf.acegisecurity.util.FilterToBeanProxy + + targetClass + net.sf.acegisecurity.ui.basicauth.BasicProcessingFilter + @@ -53,10 +49,10 @@ Acegi HTTP Request Security Filter - net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter + net.sf.acegisecurity.util.FilterToBeanProxy - loginFormUrl - /acegilogin.jsp + targetClass + net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter