Spring Security 過濾流程

經過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}
相關文章
相關標籤/搜索