通过Debug,最原始的过滤器链是Tomcat的ApplicationFilterChain。
org.apache.catalina.core.ApplicationFilterChain implements javax.servlet.FilterChain { // 实例是一个 DispatchServlet private Servlet servlet; // 过滤器数组 private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0]; // 当前的过滤器位置 private int pos; // 过滤器总数 private int n; public void doFilter(ServletRequest request, ServletResponse response) { internalDoFilter(request,response); } private void internalDoFilter(ServletRequest request, ServletResponse response) { if (pos < n) { ApplicationFilterConfig filterConfig = filters[pos++]; Filter filter = filterConfig.getFilter(); filter.doFilter(request, response, this); } }}
这里面有6个过滤器,分别是
0 ApplicationFilterConfig[name=characterEncodingFilter, filterClass=org.springframework.boot.web.servlet.filter.OrderedCharacterEncodingFilter]1 ApplicationFilterConfig[name=hiddenHttpMethodFilter, filterClass=org.springframework.boot.web.servlet.filter.OrderedHiddenHttpMethodFilter]2 ApplicationFilterConfig[name=httpPutFormContentFilter, filterClass=org.springframework.boot.web.servlet.filter.OrderedHttpPutFormContentFilter]3 ApplicationFilterConfig[name=requestContextFilter, filterClass=org.springframework.boot.web.servlet.filter.OrderedRequestContextFilter]4 ApplicationFilterConfig[name=springSecurityFilterChain, filterClass=org.springframework.boot.web.servlet.DelegatingFilterProxyRegistrationBean$1]5 ApplicationFilterConfig[name=Tomcat WebSocket (JSR356) Filter, filterClass=org.apache.tomcat.websocket.server.WsFilter]
Spring boot 以“springSecurityFilterChain”为名字,向容器注入DelegatingFilterProxyRegistrationBean,这个bean被包装成ApplicationFilterConfig, 以便通过getFilter()获取Filter。
这里应该是动态代理(这个暂时没想清楚),当调用filter.doFilter的时候,这个filter实际上是DelegatingFilterProxy。
public class DelegatingFilterProxy extends GenericFilterBean { private volatile Filter delegate; public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) { Filter delegateToUse = this.delegate; invokeDelegate(delegateToUse, request, response, filterChain); } protected void invokeDelegate( Filter delegate, ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException { delegate.doFilter(request, response, filterChain); }}
这里的 delegate 毫无疑问是 FilterChainProxy。
FilterChainProxy就带着一开始的ApplicationFilterChain,开始自己的过滤生涯,doFilter...
public class FilterChainProxy extends GenericFilterBean { public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { doFilterInternal(request, response, chain); } private void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // wrap FirewalledRequest fwRequest = firewall .getFirewalledRequest((HttpServletRequest) request); HttpServletResponse fwResponse = firewall .getFirewalledResponse((HttpServletResponse) response); // 根据请求匹配 security 过滤器 Listfilters = getFilters(fwRequest); // 如果没有配置 security 过滤器 if (filters == null || filters.size() == 0) { // reset fwRequest.reset(); // 那么继续原始的过滤器链 ApplicationFilterChain chain.doFilter(fwRequest, fwResponse); } VirtualFilterChain vfc = new VirtualFilterChain(fwRequest, chain, filters); vfc.doFilter(fwRequest, fwResponse); }}
没错,FilterChainProxy根据请求,匹配到好多security过滤器,并用他们创建出一条新的过滤链 VirtualFilterChain。
private static class VirtualFilterChain implements FilterChain { // 原始的 ApplicationFilterChain private final FilterChain originalChain; // security filters private final ListadditionalFilters; private final FirewalledRequest firewalledRequest; private final int size; private int currentPosition = 0; v @Override public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { // VirtualFilterChain 过滤完成 if (currentPosition == size) { // reset this.firewalledRequest.reset(); // 继续原始链 originalChain.doFilter(request, response); } // 执行过滤器 else { currentPosition++; Filter nextFilter = additionalFilters.get(currentPosition - 1); nextFilter.doFilter(request, response, this); } }}
而这条新过滤链的过滤器数组,正是
additionalFilters = {ArrayList@6631} size = 13 0 = {WebAsyncManagerIntegrationFilter@6634} 1 = {SecurityContextPersistenceFilter@6471} 2 = {HeaderWriterFilter@6470} 3 = {CsrfFilter@6469} 4 = {LogoutFilter@6468} 5 = {CustomUsernamePasswordAuthenticationFilter@6467} 6 = {UsernamePasswordAuthenticationFilter@6466} 7 = {RequestCacheAwareFilter@6465} 8 = {SecurityContextHolderAwareRequestFilter@6462} 9 = {AnonymousAuthenticationFilter@6458} 10 = {SessionManagementFilter@6457} 12 = {FilterSecurityInterceptor@6635} 11 = {ExceptionTranslationFilter@6455}