From 4e09777dec07f87ef62949fc6868085f90a01390 Mon Sep 17 00:00:00 2001 From: Ben Alex Date: Wed, 26 Apr 2006 03:55:39 +0000 Subject: [PATCH] SEC-247: Allow #NONE# to be used to specify paths that shouldn't have any filters fire. --- .../acegisecurity/util/FilterChainProxy.java | 110 ++++++++++-------- .../util/FilterChainProxyTests.java | 36 ++++-- .../acegisecurity/util/filtertest-valid.xml | 1 + 3 files changed, 91 insertions(+), 56 deletions(-) diff --git a/core/src/main/java/org/acegisecurity/util/FilterChainProxy.java b/core/src/main/java/org/acegisecurity/util/FilterChainProxy.java index eb40f62cab..20f8888bd4 100644 --- a/core/src/main/java/org/acegisecurity/util/FilterChainProxy.java +++ b/core/src/main/java/org/acegisecurity/util/FilterChainProxy.java @@ -1,4 +1,4 @@ -/* Copyright 2004, 2005 Acegi Technology Pty Limited +/* Copyright 2004, 2005, 2006 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. @@ -17,6 +17,7 @@ package org.acegisecurity.util; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; + import org.acegisecurity.intercept.web.FilterInvocation; import org.acegisecurity.intercept.web.FilterInvocationDefinitionSource; @@ -28,6 +29,7 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; + import org.springframework.util.Assert; import java.io.IOException; @@ -90,16 +92,20 @@ import javax.servlet.ServletResponse; *

* It is particularly noted the Filter lifecycle mismatch between * the servlet container and IoC container. As per {@link - * org.acegisecurity.util.FilterToBeanProxy} JavaDocs, we recommend you - * allow the IoC container to manage lifecycle instead of the servlet - * container. By default the FilterToBeanProxy will never call - * this class' {@link #init(FilterConfig)} and {@link #destroy()} methods, - * meaning each of the filters defined against - * FilterInvocationDefinitionSource will not be called. If you do - * need your filters to be initialized and destroyed, please set the - * lifecycle initialization parameter against the - * FilterToBeanProxy to specify servlet container lifecycle - * management. + * org.acegisecurity.util.FilterToBeanProxy} JavaDocs, we recommend you allow + * the IoC container to manage lifecycle instead of the servlet container. By + * default the FilterToBeanProxy will never call this class' + * {@link #init(FilterConfig)} and {@link #destroy()} methods, meaning each of + * the filters defined against FilterInvocationDefinitionSource + * will not be called. If you do need your filters to be initialized and + * destroyed, please set the lifecycle initialization parameter + * against the FilterToBeanProxy to specify servlet container + * lifecycle management. + *

+ * + *

+ * If a filter name of {@link #TOKEN_NONE} is used, this allows specification + * of a filter pattern which should never cause any filters to fire. *

* * @author Carlos Sanchez @@ -111,6 +117,7 @@ public class FilterChainProxy implements Filter, InitializingBean, //~ Static fields/initializers ============================================= private static final Log logger = LogFactory.getLog(FilterChainProxy.class); + public static final String TOKEN_NONE = "#NONE#"; //~ Instance fields ======================================================== @@ -119,36 +126,27 @@ public class FilterChainProxy implements Filter, InitializingBean, //~ Methods ================================================================ - public void setApplicationContext(ApplicationContext applicationContext) - throws BeansException { - this.applicationContext = applicationContext; - } - - public void setFilterInvocationDefinitionSource( - FilterInvocationDefinitionSource filterInvocationDefinitionSource) { - this.filterInvocationDefinitionSource = filterInvocationDefinitionSource; - } - - public FilterInvocationDefinitionSource getFilterInvocationDefinitionSource() { - return filterInvocationDefinitionSource; - } - public void afterPropertiesSet() throws Exception { - Assert.notNull(filterInvocationDefinitionSource, "filterInvocationDefinitionSource must be specified"); - Assert.notNull(this.filterInvocationDefinitionSource.getConfigAttributeDefinitions(), "FilterChainProxy requires the FilterInvocationDefinitionSource to return a non-null response to getConfigAttributeDefinitions()"); + Assert.notNull(filterInvocationDefinitionSource, + "filterInvocationDefinitionSource must be specified"); + Assert.notNull(this.filterInvocationDefinitionSource + .getConfigAttributeDefinitions(), + "FilterChainProxy requires the FilterInvocationDefinitionSource to return a non-null response to getConfigAttributeDefinitions()"); } public void destroy() { Filter[] filters = obtainAllDefinedFilters(); for (int i = 0; i < filters.length; i++) { - if (logger.isDebugEnabled()) { - logger.debug( - "Destroying Filter defined in ApplicationContext: '" - + filters[i].toString() + "'"); - } + if (filters[i] != null) { + if (logger.isDebugEnabled()) { + logger.debug( + "Destroying Filter defined in ApplicationContext: '" + + filters[i].toString() + "'"); + } - filters[i].destroy(); + filters[i].destroy(); + } } } @@ -174,17 +172,23 @@ public class FilterChainProxy implements Filter, InitializingBean, } } + public FilterInvocationDefinitionSource getFilterInvocationDefinitionSource() { + return filterInvocationDefinitionSource; + } + public void init(FilterConfig filterConfig) throws ServletException { Filter[] filters = obtainAllDefinedFilters(); for (int i = 0; i < filters.length; i++) { - if (logger.isDebugEnabled()) { - logger.debug( - "Initializing Filter defined in ApplicationContext: '" - + filters[i].toString() + "'"); - } + if (filters[i] != null) { + if (logger.isDebugEnabled()) { + logger.debug( + "Initializing Filter defined in ApplicationContext: '" + + filters[i].toString() + "'"); + } - filters[i].init(filterConfig); + filters[i].init(filterConfig); + } } } @@ -231,11 +235,8 @@ public class FilterChainProxy implements Filter, InitializingBean, * Filters * * @return the Filters against the specified - * ConfigAttributeDefinition - * - * @throws IllegalArgumentException if a configuration attribute provides a - * null return value from the {@link - * ConfigAttribute#getAttribute()} method + * ConfigAttributeDefinition (never + * null) */ private Filter[] obtainAllDefinedFilters( ConfigAttributeDefinition configAttributeDefinition) { @@ -246,16 +247,29 @@ public class FilterChainProxy implements Filter, InitializingBean, ConfigAttribute attr = (ConfigAttribute) attributes.next(); String filterName = attr.getAttribute(); - Assert.notNull(filterName, "Configuration attribute: '" - + attr - + "' returned null to the getAttribute() method, which is invalid when used with FilterChainProxy"); + Assert.notNull(filterName, + "Configuration attribute: '" + attr + + "' returned null to the getAttribute() method, which is invalid when used with FilterChainProxy"); - list.add(this.applicationContext.getBean(filterName, Filter.class)); + if (!filterName.equals(TOKEN_NONE)) { + list.add(this.applicationContext.getBean(filterName, + Filter.class)); + } } return (Filter[]) list.toArray(new Filter[] {null}); } + public void setApplicationContext(ApplicationContext applicationContext) + throws BeansException { + this.applicationContext = applicationContext; + } + + public void setFilterInvocationDefinitionSource( + FilterInvocationDefinitionSource filterInvocationDefinitionSource) { + this.filterInvocationDefinitionSource = filterInvocationDefinitionSource; + } + //~ Inner Classes ========================================================== /** diff --git a/core/src/test/java/org/acegisecurity/util/FilterChainProxyTests.java b/core/src/test/java/org/acegisecurity/util/FilterChainProxyTests.java index d40f5fac34..738063e730 100644 --- a/core/src/test/java/org/acegisecurity/util/FilterChainProxyTests.java +++ b/core/src/test/java/org/acegisecurity/util/FilterChainProxyTests.java @@ -1,4 +1,4 @@ -/* Copyright 2004, 2005 Acegi Technology Pty Limited +/* Copyright 2004, 2005, 2006 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. @@ -21,12 +21,14 @@ import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.MockApplicationContext; import org.acegisecurity.MockFilterConfig; + import org.acegisecurity.intercept.web.FilterInvocationDefinitionSource; import org.acegisecurity.intercept.web.MockFilterInvocationDefinitionSource; import org.acegisecurity.intercept.web.PathBasedFilterInvocationDefinitionMap; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; + import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; @@ -60,8 +62,7 @@ public class FilterChainProxyTests extends TestCase { public void testDetectsFilterInvocationDefinitionSourceThatDoesNotReturnAllConfigAttributes() throws Exception { FilterChainProxy filterChainProxy = new FilterChainProxy(); - filterChainProxy.setApplicationContext(MockApplicationContext - .getContext()); + filterChainProxy.setApplicationContext(MockApplicationContext.getContext()); filterChainProxy.setFilterInvocationDefinitionSource(new MockFilterInvocationDefinitionSource( false, false)); @@ -77,8 +78,7 @@ public class FilterChainProxyTests extends TestCase { public void testDetectsIfConfigAttributeDoesNotReturnValueForGetAttributeMethod() throws Exception { FilterChainProxy filterChainProxy = new FilterChainProxy(); - filterChainProxy.setApplicationContext(MockApplicationContext - .getContext()); + filterChainProxy.setApplicationContext(MockApplicationContext.getContext()); ConfigAttributeDefinition cad = new ConfigAttributeDefinition(); cad.addConfigAttribute(new MockConfigAttribute()); @@ -93,15 +93,15 @@ public class FilterChainProxyTests extends TestCase { filterChainProxy.init(new MockFilterConfig()); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { - assertTrue(expected.getMessage().endsWith("returned null to the getAttribute() method, which is invalid when used with FilterChainProxy")); + assertTrue(expected.getMessage() + .endsWith("returned null to the getAttribute() method, which is invalid when used with FilterChainProxy")); } } public void testDetectsMissingFilterInvocationDefinitionSource() throws Exception { FilterChainProxy filterChainProxy = new FilterChainProxy(); - filterChainProxy.setApplicationContext(MockApplicationContext - .getContext()); + filterChainProxy.setApplicationContext(MockApplicationContext.getContext()); try { filterChainProxy.afterPropertiesSet(); @@ -112,6 +112,26 @@ public class FilterChainProxyTests extends TestCase { } } + public void testDoNotFilter() throws Exception { + ApplicationContext appCtx = new ClassPathXmlApplicationContext( + "org/acegisecurity/util/filtertest-valid.xml"); + FilterChainProxy filterChainProxy = (FilterChainProxy) appCtx.getBean("filterChain", + FilterChainProxy.class); + MockFilter filter = (MockFilter) appCtx.getBean("mockFilter", + MockFilter.class); + + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setServletPath("/do/not/filter/somefile.html"); + + MockHttpServletResponse response = new MockHttpServletResponse(); + MockFilterChain chain = new MockFilterChain(true); + + filterChainProxy.doFilter(request, response, chain); + assertFalse(filter.isWasInitialized()); + assertFalse(filter.isWasDoFiltered()); + assertFalse(filter.isWasDestroyed()); + } + public void testGettersSetters() { FilterChainProxy filterChainProxy = new FilterChainProxy(); FilterInvocationDefinitionSource fids = new MockFilterInvocationDefinitionSource(false, diff --git a/core/src/test/resources/org/acegisecurity/util/filtertest-valid.xml b/core/src/test/resources/org/acegisecurity/util/filtertest-valid.xml index 5e312a5dab..6e8bf3c132 100644 --- a/core/src/test/resources/org/acegisecurity/util/filtertest-valid.xml +++ b/core/src/test/resources/org/acegisecurity/util/filtertest-valid.xml @@ -34,6 +34,7 @@ PATTERN_TYPE_APACHE_ANT /foo/**=mockFilter /some/other/path/**=mockFilter + /do/not/filter=#NONE#