Polishing FilterChainProxy and its tests.
This commit is contained in:
parent
6abfa2e887
commit
591bd532bd
|
@ -73,43 +73,43 @@ public class FilterChainProxyConfigTests {
|
|||
|
||||
@Test
|
||||
public void normalOperation() throws Exception {
|
||||
FilterChainProxy filterChainProxy = (FilterChainProxy) appCtx.getBean("filterChain", FilterChainProxy.class);
|
||||
FilterChainProxy filterChainProxy = appCtx.getBean("filterChain", FilterChainProxy.class);
|
||||
doNormalOperation(filterChainProxy);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void normalOperationWithNewConfig() throws Exception {
|
||||
FilterChainProxy filterChainProxy = (FilterChainProxy) appCtx.getBean("newFilterChainProxy", FilterChainProxy.class);
|
||||
FilterChainProxy filterChainProxy = appCtx.getBean("newFilterChainProxy", FilterChainProxy.class);
|
||||
checkPathAndFilterOrder(filterChainProxy);
|
||||
doNormalOperation(filterChainProxy);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void normalOperationWithNewConfigRegex() throws Exception {
|
||||
FilterChainProxy filterChainProxy = (FilterChainProxy) appCtx.getBean("newFilterChainProxyRegex", FilterChainProxy.class);
|
||||
FilterChainProxy filterChainProxy = appCtx.getBean("newFilterChainProxyRegex", FilterChainProxy.class);
|
||||
checkPathAndFilterOrder(filterChainProxy);
|
||||
doNormalOperation(filterChainProxy);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void normalOperationWithNewConfigNonNamespace() throws Exception {
|
||||
FilterChainProxy filterChainProxy = (FilterChainProxy) appCtx.getBean("newFilterChainProxyNonNamespace", FilterChainProxy.class);
|
||||
FilterChainProxy filterChainProxy = appCtx.getBean("newFilterChainProxyNonNamespace", FilterChainProxy.class);
|
||||
checkPathAndFilterOrder(filterChainProxy);
|
||||
doNormalOperation(filterChainProxy);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathWithNoMatchHasNoFilters() throws Exception {
|
||||
FilterChainProxy filterChainProxy = (FilterChainProxy) appCtx.getBean("newFilterChainProxyNoDefaultPath", FilterChainProxy.class);
|
||||
FilterChainProxy filterChainProxy = appCtx.getBean("newFilterChainProxyNoDefaultPath", FilterChainProxy.class);
|
||||
assertEquals(null, filterChainProxy.getFilters("/nomatch"));
|
||||
}
|
||||
|
||||
// SEC-1235
|
||||
@Test
|
||||
public void mixingPatternsAndPlaceholdersDoesntCauseOrderingIssues() throws Exception {
|
||||
FilterChainProxy filterChainProxy = (FilterChainProxy) appCtx.getBean("sec1235FilterChainProxy", FilterChainProxy.class);
|
||||
FilterChainProxy fcp = appCtx.getBean("sec1235FilterChainProxy", FilterChainProxy.class);
|
||||
|
||||
RequestMatcher[] matchers = filterChainProxy.getFilterChainMap().keySet().toArray(new RequestMatcher[0]);
|
||||
RequestMatcher[] matchers = fcp.getFilterChainMap().keySet().toArray(new RequestMatcher[fcp.getFilterChainMap().keySet().size()]);
|
||||
assertEquals("/login*", ((AntPathRequestMatcher)matchers[0]).getPattern());
|
||||
assertEquals("/logout", ((AntPathRequestMatcher)matchers[1]).getPattern());
|
||||
assertTrue(matchers[2] instanceof AnyRequestMatcher);
|
||||
|
|
|
@ -15,22 +15,6 @@
|
|||
|
||||
package org.springframework.security.web;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.security.web.util.AnyRequestMatcher;
|
||||
|
@ -39,6 +23,11 @@ import org.springframework.util.Assert;
|
|||
import org.springframework.web.filter.DelegatingFilterProxy;
|
||||
import org.springframework.web.filter.GenericFilterBean;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
* Delegates <code>Filter</code> requests to a list of Spring-managed beans.
|
||||
|
@ -96,7 +85,6 @@ public class FilterChainProxy extends GenericFilterBean {
|
|||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
private static final Log logger = LogFactory.getLog(FilterChainProxy.class);
|
||||
public static final String TOKEN_NONE = "#NONE#";
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
|
@ -121,7 +109,7 @@ public class FilterChainProxy extends GenericFilterBean {
|
|||
if (filters == null || filters.size() == 0) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(fi.getRequestUrl() +
|
||||
filters == null ? " has no matching filters" : " has an empty filter list");
|
||||
(filters == null ? " has no matching filters" : " has an empty filter list"));
|
||||
}
|
||||
|
||||
chain.doFilter(request, response);
|
||||
|
@ -162,26 +150,6 @@ public class FilterChainProxy extends GenericFilterBean {
|
|||
return getFilters(new FilterInvocation(url, null).getRequest());
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains all of the <b>unique</b><code>Filter</code> instances registered in the map of
|
||||
* filter chains.
|
||||
* <p>This is useful in ensuring a <code>Filter</code> is not initialized or destroyed twice.</p>
|
||||
*
|
||||
* @return all of the <code>Filter</code> instances in the application context which have an entry
|
||||
* in the map (only one entry is included in the array for
|
||||
* each <code>Filter</code> that actually exists in application context, even if a given
|
||||
* <code>Filter</code> is defined multiples times in the filter chain map)
|
||||
*/
|
||||
protected Collection<Filter> obtainAllDefinedFilters() {
|
||||
Set<Filter> allFilters = new LinkedHashSet<Filter>();
|
||||
|
||||
for (List<Filter> filters : filterChainMap.values()) {
|
||||
allFilters.addAll(filters);
|
||||
}
|
||||
|
||||
return allFilters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the mapping of URL patterns to filter chains.
|
||||
*
|
||||
|
@ -217,10 +185,10 @@ public class FilterChainProxy extends GenericFilterBean {
|
|||
|
||||
private void checkPathOrder() {
|
||||
// Check that the universal pattern is listed at the end, if at all
|
||||
RequestMatcher[] matchers = filterChainMap.keySet().toArray(new RequestMatcher[0]);
|
||||
Iterator<RequestMatcher> matchers = filterChainMap.keySet().iterator();
|
||||
|
||||
for (int i=0; i < matchers.length-1; i++) {
|
||||
if (matchers[i] instanceof AnyRequestMatcher) {
|
||||
while(matchers.hasNext()) {
|
||||
if ((matchers.next() instanceof AnyRequestMatcher && matchers.hasNext())) {
|
||||
throw new IllegalArgumentException("A universal match pattern ('/**') is defined " +
|
||||
" before other patterns in the filter chain, causing them to be ignored. Please check the " +
|
||||
"ordering in your <security:http> namespace or FilterChainProxy bean configuration");
|
||||
|
@ -241,7 +209,8 @@ public class FilterChainProxy extends GenericFilterBean {
|
|||
/**
|
||||
* Used (internally) to specify a validation strategy for the filters in each configured chain.
|
||||
*
|
||||
* @param filterChainValidator
|
||||
* @param filterChainValidator the validator instance which will be invoked on during initialization
|
||||
* to check the {@code FilterChainProxy} instance.
|
||||
*/
|
||||
public void setFilterChainValidator(FilterChainValidator filterChainValidator) {
|
||||
this.filterChainValidator = filterChainValidator;
|
||||
|
@ -260,24 +229,25 @@ public class FilterChainProxy extends GenericFilterBean {
|
|||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
/**
|
||||
* A <code>FilterChain</code> that records whether or not {@link
|
||||
* FilterChain#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse)} is called.
|
||||
* <p>
|
||||
* This <code>FilterChain</code> is used by <code>FilterChainProxy</code> to determine if the next
|
||||
* <code>Filter</code> should be called or not.</p>
|
||||
* Internal {@code FilterChain} implementation that is used to pass a request through the additional
|
||||
* internal list of filters which match the request. Records the position in the additional filter chain and, when
|
||||
* completed, passes the request back to the original {@code FilterChain} supplied by the servlet container.
|
||||
*/
|
||||
private static class VirtualFilterChain implements FilterChain {
|
||||
private final FilterInvocation fi;
|
||||
private final List<Filter> additionalFilters;
|
||||
private final int size;
|
||||
private int currentPosition = 0;
|
||||
|
||||
|
||||
private VirtualFilterChain(FilterInvocation filterInvocation, List<Filter> additionalFilters) {
|
||||
this.fi = filterInvocation;
|
||||
this.additionalFilters = additionalFilters;
|
||||
this.size = additionalFilters.size();
|
||||
}
|
||||
|
||||
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
|
||||
if (currentPosition == additionalFilters.size()) {
|
||||
if (currentPosition == size) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(fi.getRequestUrl()
|
||||
+ " reached end of additional filter chain; proceeding with original chain");
|
||||
|
@ -291,7 +261,7 @@ public class FilterChainProxy extends GenericFilterBean {
|
|||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(fi.getRequestUrl() + " at position " + currentPosition + " of "
|
||||
+ additionalFilters.size() + " in additional filter chain; firing Filter: '"
|
||||
+ size + " in additional filter chain; firing Filter: '"
|
||||
+ nextFilter + "'");
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue