上一篇文章中提到了名为springSecurityFilterChain的bean在Spring容器中的注册过程。它所代表的类即为org.springframework.security.web.FilterChainProxy.

所以所有的url请求实际上都会经过这个过滤器代理。让我们查看一下他的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);
        }
    }

由此可见,他会再次经过doFilterInternal   方法

    private void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        FirewalledRequest fwRequest = firewall.getFirewalledRequest((HttpServletRequest) request);
        HttpServletResponse fwResponse = firewall.getFirewalledResponse((HttpServletResponse) response);
        这个getFilters方法得到的过滤器就是在进行配置文件解析时,security组件注册的一些过滤器
        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();

            chain.doFilter(fwRequest, fwResponse);

            return;
        }

        VirtualFilterChain vfc = new VirtualFilterChain(fwRequest, chain, filters);
        //请求转入vfc的doFilter方法
       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();

                originalChain.doFilter(request, response);
            } else {
                currentPosition++;
                此实现就是一个过滤链的一个实现方式
                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() + "'");
                }

                nextFilter.doFilter(request, response, this);
            }
        }


Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐