FilterChainProxy本是个javax.servlet.Filter(在org.springframework.security.config.annotation.web.builders.WebSecurity中被创建),它内部维护着多个SecurityFilterChain的引用,而每个SecurityFilterChain内部维持着多个Filter的引用,并且还有一个用于判断某HttpServletRequest是否满足条件的“匹配器”。
FilterChainProxy 的实现是比较简单的,下面对源码进行分析:
public class FilterChainProxy extends GenericFilterBean {
// ~ Static fields/initializers
// =====================================================================================
private static final Log logger = LogFactory.getLog(FilterChainProxy.class);
// ~ Instance fields
// ================================================================================================
private final static String FILTER_APPLIED = FilterChainProxy.class.getName().concat(
".APPLIED");
//外部传递进来的SecurityFilterChain集合【SecurityFilterChain】
private List<SecurityFilterChain> filterChains;
private FilterChainValidator filterChainValidator = new NullFilterChainValidator();
//用于拒绝任何可疑请求。
private HttpFirewall firewall = new StrictHttpFirewall();
// ~ Methods
// ========================================================================================================
public FilterChainProxy() {
}
public FilterChainProxy(SecurityFilterChain chain) {
this(Arrays.asList(chain));
}
public FilterChainProxy(List<SecurityFilterChain> filterChains) {
this.filterChains = filterChains;
}
@Override
public void afterPropertiesSet() {
filterChainValidator.validate(this);
}
//接收HTTP请求
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
boolean clearContext = request.getAttribute(FILTER_APPLIED) == null;
if (clearContext) {
try {
request.setAttribute(FILTER_APPLIED, Boolean.TRUE);
doFilterInternal(request, response, chain);
}
finally {
SecurityContextHolder.clearContext();
request.removeAttribute(FILTER_APPLIED);
}
}
else {
doFilterInternal(request, response, chain);
}
}
private void doFilterInternal(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
//将请求进行验证和简单的包装,如果是可疑的请求则会抛出异常
FirewalledRequest fwRequest = firewall
.getFirewalledRequest((HttpServletRequest) request);
HttpServletResponse fwResponse = firewall
.getFirewalledResponse((HttpServletResponse) response);
//根据请求筛选适合该请求的Filter
List<Filter> filters = getFilters(fwRequest);
if (filters == null || filters.size() == 0) {
if (logger.isDebugEnabled()) {
logger.debug(UrlUtils.buildRequestUrl(fwRequest)
+ (filters == null ? " has no matching filters"
: " has an empty filter list"));
}
fwRequest.reset();
//继续后面的Filter
chain.doFilter(fwRequest, fwResponse);
return;
}
//将Filter集合封装,内部对Filter集合进行链式调用【对应Securty的Filter将生效】
VirtualFilterChain vfc = new VirtualFilterChain(fwRequest, chain, filters);
vfc.doFilter(fwRequest, fwResponse);
}
private List<Filter> getFilters(HttpServletRequest request) {
for (SecurityFilterChain chain : filterChains) {
if (chain.matches(request)) {
return chain.getFilters();
}
}
return null;
}
public List<Filter> getFilters(String url) {
return getFilters(firewall.getFirewalledRequest((new FilterInvocation(url, "GET")
.getRequest())));
}
public List<SecurityFilterChain> getFilterChains() {
return Collections.unmodifiableList(filterChains);
}
public void setFilterChainValidator(FilterChainValidator filterChainValidator) {
this.filterChainValidator = filterChainValidator;
}
public void setFirewall(HttpFirewall firewall) {
this.firewall = firewall;
}
// ~ Inner Classes
// ==================================================================================================
/**
* Internal {@code FilterChain} implementation that is used to pass a request through
* the additional internal list of filters which match the request.
*/
private static class VirtualFilterChain implements FilterChain {
private final FilterChain originalChain;
private final List<Filter> additionalFilters;
private final FirewalledRequest firewalledRequest;
private final int size;
private int currentPosition = 0;
private VirtualFilterChain(FirewalledRequest firewalledRequest,
FilterChain chain, List<Filter> additionalFilters) {
this.originalChain = chain;
this.additionalFilters = additionalFilters;
this.size = additionalFilters.size();
this.firewalledRequest = firewalledRequest;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
if (currentPosition == size) {
if (logger.isDebugEnabled()) {
logger.debug(UrlUtils.buildRequestUrl(firewalledRequest)
+ " reached end of additional filter chain; proceeding with original chain");
}
// Deactivate path stripping as we exit the security filter chain
this.firewalledRequest.reset();
originalChain.doFilter(request, response);
}
else {
currentPosition++;
Filter nextFilter = additionalFilters.get(currentPosition - 1);
if (logger.isDebugEnabled()) {
logger.debug(UrlUtils.buildRequestUrl(firewalledRequest)
+ " at position " + currentPosition + " of " + size
+ " in additional filter chain; firing Filter: '"
+ nextFilter.getClass().getSimpleName() + "'");
}
nextFilter.doFilter(request, response, this);
}
}
}
public interface FilterChainValidator {
void validate(FilterChainProxy filterChainProxy);
}
private static class NullFilterChainValidator implements FilterChainValidator {
@Override
public void validate(FilterChainProxy filterChainProxy) {
}
}
}
可见,FilterChainProxy的目的就是拦截正常的Http请求,然后根据请求筛选出符合要求的Filter,然后链式的执行这些Filter,最后继续执行原有的FilterChain.
小结
我们简单总结下整个流程:
一个WebSecurityConfigurer对应一个SecurityFilterChain;
一个SecurityFilterChain对应多个Filter,并有一个用于判断是否应用到某个请求上的匹配器RequestMatcher
一个FilterChainProxy对应多个SecurityFilterChain;
一个DelegatingFilterProxyRegistrationBean 委托一个FilterChainProxy;
DelegatingFilterProxyRegistrationBean 通过内部创建DelegatingFilterProxy来作为springSecurityFilterChain的委托对象,并在Tomcat的启动过程中添加到ServletContext中