SpringSecurity 采用责任链模式,维护了一个很多过滤器组成的过滤器链。
1. DelegatingFilterProxy本身是个Filter,继承自GenericFilterBean,以下DelegatingFilterProxy内的doFilter方法
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException { Filter delegateToUse = this.delegate; if (delegateToUse == null) { synchronized(this.delegateMonitor) { delegateToUse = this.delegate; if (delegateToUse == null) { WebApplicationContext wac = this.findWebApplicationContext(); if (wac == null) { throw new IllegalStateException("No WebApplicationContext found: no ContextLoaderListener or DispatcherServlet registered?"); } delegateToUse = this.initDelegate(wac); } this.delegate = delegateToUse; } } this.invokeDelegate(delegateToUse, request, response, filterChain); }
调用this.initDelegate()方法
protected Filter initDelegate(WebApplicationContext wac) throws ServletException { String targetBeanName = this.getTargetBeanName(); Assert.state(targetBeanName != null, "No target bean name set"); Filter delegate = (Filter)wac.getBean(targetBeanName, Filter.class); if (this.isTargetFilterLifecycle()) { delegate.init(this.getFilterConfig()); } return delegate; }
initDelegate方法返回的delegateToUse为FilterChainProxy
调用this.invokeDelegate方法
protected void invokeDelegate(Filter delegate, ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException { delegate.doFilter(request, response, filterChain); }
这里实际是调用FilterChainProxy的doFilter如下:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { boolean clearContext = request.getAttribute(FILTER_APPLIED) == null; if (!clearContext) { this.doFilterInternal(request, response, chain); } else { try { request.setAttribute(FILTER_APPLIED, Boolean.TRUE); this.doFilterInternal(request, response, chain); } catch (Exception var11) { Throwable[] causeChain = this.throwableAnalyzer.determineCauseChain(var11); Throwable requestRejectedException = this.throwableAnalyzer.getFirstThrowableOfType(RequestRejectedException.class, causeChain); if (!(requestRejectedException instanceof RequestRejectedException)) { throw var11; } this.requestRejectedHandler.handle((HttpServletRequest)request, (HttpServletResponse)response, (RequestRejectedException)requestRejectedException); } finally { SecurityContextHolder.clearContext(); request.removeAttribute(FILTER_APPLIED); } } }
然后获取过滤器链,调用doFilterInternal方法
private void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { FirewalledRequest firewallRequest = this.firewall.getFirewalledRequest((HttpServletRequest)request); HttpServletResponse firewallResponse = this.firewall.getFirewalledResponse((HttpServletResponse)response); List<Filter> filters = this.getFilters((HttpServletRequest)firewallRequest); if (filters != null && filters.size() != 0) { if (logger.isDebugEnabled()) { logger.debug(LogMessage.of(() -> { return "Securing " + requestLine(firewallRequest); })); } FilterChainProxy.VirtualFilterChain virtualFilterChain = new FilterChainProxy.VirtualFilterChain(firewallRequest, chain, filters); virtualFilterChain.doFilter(firewallRequest, firewallResponse); } else { if (logger.isTraceEnabled()) { logger.trace(LogMessage.of(() -> { return "No security for " + requestLine(firewallRequest); })); } firewallRequest.reset(); chain.doFilter(firewallRequest, firewallResponse); } }
在doFilterInternal中创建了过滤器链对象VirtualFilterChain并调用VirtualFilterChain的doFilter方法执行自定义的过滤器集合,当自定义的过滤器集合执行完毕后,再执行原有的过滤器链
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { if (this.currentPosition == this.size) { if (FilterChainProxy.logger.isDebugEnabled()) { FilterChainProxy.logger.debug(LogMessage.of(() -> { return "Secured " + FilterChainProxy.requestLine(this.firewalledRequest); })); } this.firewalledRequest.reset(); this.originalChain.doFilter(request, response); } else { ++this.currentPosition; Filter nextFilter = (Filter)this.additionalFilters.get(this.currentPosition - 1); if (FilterChainProxy.logger.isTraceEnabled()) { FilterChainProxy.logger.trace(LogMessage.format("Invoking %s (%d/%d)", nextFilter.getClass().getSimpleName(), this.currentPosition, this.size)); } nextFilter.doFilter(request, response, this); } }