最近在学习安全框架spring Security,想弄清楚其中实现的具体步骤,于是下定决心,研究一下Spring Security源码,这篇博客的目的是想把学习过程记录下来。学习过程中主要参考了http://dead-knight.iteye.com/blog/1511389大神的博客,然后在其基础上,进行更详细的说明
在类org.springframework.web.filter.DelegatingFilterProxy的doFilter方法中可以看到,过滤器执行流程实际上是让委托执行实际的doFilter操作
@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException { Filter delegateToUse = this.delegate; if (delegateToUse == null) { synchronized (this.delegateMonitor) { if (this.delegate == null) { WebApplicationContext wac = findWebApplicationContext(); if (wac == null) { throw new IllegalStateException("No WebApplicationContext found: no ContextLoaderListener registered?"); } // 初始化springSecurityFilterChain,详解请移步2.3 this.delegate = initDelegate(wac); } delegateToUse = this.delegate; } } // 让委托执行实际的doFilter操作 invokeDelegate(delegateToUse, request, response, filterChain); }通过前面几篇博客的分析,我们也知道这里的delegateToUse实际上是org.springframework.security.web.FilterChainProxy
接下来看FilterChainProxy中的doFilter执行流程
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { boolean clearContext = request.getAttribute(FILTER_APPLIED) == null; if (clearContext) { try { request.setAttribute(FILTER_APPLIED, Boolean.TRUE); doFilterInternal(request, response, chain); } finally { SecurityContextHolder.clearContext(); request.removeAttribute(FILTER_APPLIED); } } else { doFilterInternal(request, response, chain); } } private void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { FirewalledRequest fwRequest = firewall.getFirewalledRequest((HttpServletRequest) request); HttpServletResponse fwResponse = firewall.getFirewalledResponse((HttpServletResponse) response); List<Filter> filters = getFilters(fwRequest); if (filters == null || filters.size() == 0) { if (logger.isDebugEnabled()) { logger.debug(UrlUtils.buildRequestUrl(fwRequest) + (filters == null ? " has no matching filters" : " has an empty filter list")); } fwRequest.reset(); // 执行默认过滤器如编码过滤器EncodingFilter,转换请求方式过滤器HiddenHttpMethodFilter等 chain.doFilter(fwRequest, fwResponse); return; } // 把实际doFilter任务交给VirtualFilterChain处理 VirtualFilterChain vfc = new VirtualFilterChain(fwRequest, chain, filters); vfc.doFilter(fwRequest, fwResponse); } // VirtualFilterChain的doFilter方法 public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { // 判断是否是最后一个过滤器 if (currentPosition == size) { if (logger.isDebugEnabled()) { logger.debug(UrlUtils.buildRequestUrl(firewalledRequest) + " reached end of additional filter chain; proceeding with original chain"); } // Deactivate path stripping as we exit the security filter chain this.firewalledRequest.reset(); // 执行Filter的doFilter操作 originalChain.doFilter(request, response); } else { // 当前位置加一 currentPosition++; // 根据当前位置从过滤器列表中取出一个Filter Filter nextFilter = additionalFilters.get(currentPosition - 1); if (logger.isDebugEnabled()) { logger.debug(UrlUtils.buildRequestUrl(firewalledRequest) + " at position " + currentPosition + " of " + size + " in additional filter chain; firing Filter: '" + nextFilter.getClass().getSimpleName() + "'"); } // 执行Filte r的doFilter操作 // 把自身作为参数传递给doFilter方法,这样doFilter方法最后会调用VirtualFilterChain的doFilter方法,这样控制就又回到了VirtualFilterChain nextFilter.doFilter(request, response, this); } }下一篇博客将介绍各个过滤器的具体功能