經過Debug,最原始的過濾器鏈是Tomcat的ApplicationFilterChain。java
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個過濾器,分別是web
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。spring
這裏應該是動態代理(這個暫時沒想清楚),當調用filter.doFilter的時候,這個filter其實是DelegatingFilterProxy。apache
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...tomcat
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 過濾器 List<Filter> filters = 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。websocket
private static class VirtualFilterChain implements FilterChain { // 原始的 ApplicationFilterChain private final FilterChain originalChain; // security filters private final List<Filter> additionalFilters; 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); } } }
而這條新過濾鏈的過濾器數組,正是socket
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}