1
0
mirror of synced 2026-08-06 02:08:01 +00:00

Extract a SecurityFilterChain interface and create a default implementation to facilitate other configuration options.

This commit is contained in:
Luke Taylor
2011-07-06 00:12:48 +01:00
parent 2d271666a4
commit f92589f051
10 changed files with 101 additions and 79 deletions
@@ -0,0 +1,45 @@
package org.springframework.security.web;
import org.springframework.security.web.util.RequestMatcher;
import javax.servlet.Filter;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
/**
* Standard implementation of {@code SecurityFilterChain}.
*
* @author Luke Taylor
*
* @since 3.1
*/
public final class DefaultSecurityFilterChain implements SecurityFilterChain {
private final RequestMatcher requestMatcher;
private final List<Filter> filters;
public DefaultSecurityFilterChain(RequestMatcher requestMatcher, Filter... filters) {
this(requestMatcher, Arrays.asList(filters));
}
public DefaultSecurityFilterChain(RequestMatcher requestMatcher, List<Filter> filters) {
this.requestMatcher = requestMatcher;
this.filters = new ArrayList<Filter>(filters);
}
public RequestMatcher getRequestMatcher() {
return requestMatcher;
}
public List<Filter> getFilters() {
return filters;
}
public boolean matches(HttpServletRequest request) {
return requestMatcher.matches(request);
}
@Override
public String toString() {
return "[ " + requestMatcher + ", " + filters + "]";
}
}
@@ -142,7 +142,6 @@ public class FilterChainProxy extends GenericFilterBean {
public FilterChainProxy(List<SecurityFilterChain> filterChains) {
this.filterChains = filterChains;
checkPathOrder();
}
@Override
@@ -219,10 +218,8 @@ public class FilterChainProxy extends GenericFilterBean {
filterChains = new ArrayList<SecurityFilterChain>(filterChainMap.size());
for (Map.Entry<RequestMatcher,List<Filter>> entry : filterChainMap.entrySet()) {
filterChains.add(new SecurityFilterChain(entry.getKey(), entry.getValue()));
filterChains.add(new DefaultSecurityFilterChain(entry.getKey(), entry.getValue()));
}
checkPathOrder();
}
/**
@@ -238,25 +235,12 @@ public class FilterChainProxy extends GenericFilterBean {
LinkedHashMap<RequestMatcher, List<Filter>> map = new LinkedHashMap<RequestMatcher, List<Filter>>();
for (SecurityFilterChain chain : filterChains) {
map.put(chain.getRequestMatcher(), chain.getFilters());
map.put(((DefaultSecurityFilterChain)chain).getRequestMatcher(), chain.getFilters());
}
return map;
}
private void checkPathOrder() {
// Check that the universal pattern is listed at the end, if at all
Iterator<SecurityFilterChain> chains = filterChains.iterator();
while(chains.hasNext()) {
if ((chains.next().getRequestMatcher() instanceof AnyRequestMatcher && chains.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");
}
}
}
/**
* @return the list of {@code SecurityFilterChain}s which will be matched against and
* applied to incoming requests.
@@ -1,54 +1,23 @@
package org.springframework.security.web;
import org.springframework.security.web.util.RequestMatcher;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.*;
/**
* Bean which defines a filter chain which is capable of being matched against an {@code HttpServletRequest}.
* Defines a filter chain which is capable of being matched against an {@code HttpServletRequest}.
* in order to decide whether it applies to that request.
* <p>
* Used to configure a {@code FilterChainProxy}.
*
*
* @author Luke Taylor
*
* @since 3.1
*/
public final class SecurityFilterChain {
private final RequestMatcher requestMatcher;
private final List<Filter> filters;
public interface SecurityFilterChain {
public SecurityFilterChain(RequestMatcher requestMatcher, Filter... filters) {
this(requestMatcher, Arrays.asList(filters));
}
boolean matches(HttpServletRequest request);
public SecurityFilterChain(RequestMatcher requestMatcher, List<Filter> filters) {
this.requestMatcher = requestMatcher;
this.filters = new ArrayList<Filter>(filters);
}
public RequestMatcher getRequestMatcher() {
return requestMatcher;
}
public List<Filter> getFilters() {
return filters;
}
public boolean matches(HttpServletRequest request) {
return requestMatcher.matches(request);
}
@Override
public String toString() {
return "[ " + requestMatcher + ", " + filters + "]";
}
List<Filter> getFilters();
}
@@ -47,7 +47,7 @@ public class FilterChainProxyTests {
return null;
}
}).when(filter).doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class), any(FilterChain.class));
fcp = new FilterChainProxy(new SecurityFilterChain(matcher, Arrays.asList(filter)));
fcp = new FilterChainProxy(new DefaultSecurityFilterChain(matcher, Arrays.asList(filter)));
fcp.setFilterChainValidator(mock(FilterChainProxy.FilterChainValidator.class));
request = new MockHttpServletRequest();
request.setServletPath("/path");
@@ -94,7 +94,7 @@ public class FilterChainProxyTests {
@Test
public void originalFilterChainIsInvokedIfMatchingSecurityChainIsEmpty() throws Exception {
List<Filter> noFilters = Collections.emptyList();
fcp = new FilterChainProxy(new SecurityFilterChain(matcher, noFilters));
fcp = new FilterChainProxy(new DefaultSecurityFilterChain(matcher, noFilters));
when(matcher.matches(any(HttpServletRequest.class))).thenReturn(true);
fcp.doFilter(request, response, chain);
@@ -137,7 +137,7 @@ public class FilterChainProxyTests {
@Test
public void bothWrappersAreResetWithNestedFcps() throws Exception {
HttpFirewall fw = mock(HttpFirewall.class);
FilterChainProxy firstFcp = new FilterChainProxy(new SecurityFilterChain(matcher, fcp));
FilterChainProxy firstFcp = new FilterChainProxy(new DefaultSecurityFilterChain(matcher, fcp));
firstFcp.setFirewall(fw);
fcp.setFirewall(fw);
FirewalledRequest firstFwr = mock(FirewalledRequest.class, "firstFwr");