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}
相关文章
相关标签/搜索