SEC-247: Allow #NONE# to be used to specify paths that shouldn't have any filters fire.
This commit is contained in:
parent
185d63f23c
commit
4e09777dec
|
@ -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;
|
|||
* <p>
|
||||
* It is particularly noted the <code>Filter</code> 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 <code>FilterToBeanProxy</code> will never call
|
||||
* this class' {@link #init(FilterConfig)} and {@link #destroy()} methods,
|
||||
* meaning each of the filters defined against
|
||||
* <code>FilterInvocationDefinitionSource</code> will not be called. If you do
|
||||
* need your filters to be initialized and destroyed, please set the
|
||||
* <code>lifecycle</code> initialization parameter against the
|
||||
* <code>FilterToBeanProxy</code> 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 <code>FilterToBeanProxy</code> will never call this class'
|
||||
* {@link #init(FilterConfig)} and {@link #destroy()} methods, meaning each of
|
||||
* the filters defined against <code>FilterInvocationDefinitionSource</code>
|
||||
* will not be called. If you do need your filters to be initialized and
|
||||
* destroyed, please set the <code>lifecycle</code> initialization parameter
|
||||
* against the <code>FilterToBeanProxy</code> to specify servlet container
|
||||
* lifecycle management.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* 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.
|
||||
* </p>
|
||||
*
|
||||
* @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,
|
|||
* <code>Filter</code>s
|
||||
*
|
||||
* @return the <code>Filter</code>s against the specified
|
||||
* <code>ConfigAttributeDefinition</code>
|
||||
*
|
||||
* @throws IllegalArgumentException if a configuration attribute provides a
|
||||
* <code>null</code> return value from the {@link
|
||||
* ConfigAttribute#getAttribute()} method
|
||||
* <code>ConfigAttributeDefinition</code> (never
|
||||
* <code>null</code>)
|
||||
*/
|
||||
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 ==========================================================
|
||||
|
||||
/**
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
PATTERN_TYPE_APACHE_ANT
|
||||
/foo/**=mockFilter
|
||||
/some/other/path/**=mockFilter
|
||||
/do/not/filter=#NONE#
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
|
Loading…
Reference in New Issue