spring security

Spring Security原理篇(四) FilterChai

2018-09-18  本文已影响359人  怪诞140819

在前面的三篇文章中,已经大概交代了一下三个地方

1.为什么要说这个类

在前面的文章中我们已经说到所有的过滤器链都添加到了securityFilterChains这个列表中,后面出现了下面一行代码

FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);

我们知道FilterChainProxy的bean的名字叫做springSecurityFilterChain里面包含了我们的过滤器链
所以我们必须要清楚他的工作原理

2.类的简单说明

2.1变量

2.1.1 filterChains

变量定义

private List<SecurityFilterChain> filterChains

2.2构造函数

public FilterChainProxy(List<SecurityFilterChain> filterChains) {
        this.filterChains = filterChains;
    }

WebSecurityperformBuild()方法中我们对于spring security的配置最后生成的过滤器链设置到filterChains 这个变量中

3.虚拟过滤器链VirtualFilterChain

private static class VirtualFilterChain implements FilterChain {
                 
                //原始过滤器链,代表了spring 的application context中所有的过滤器连
               //其实可以参考DelegatingFilterProxy
        private final FilterChain originalChain;
               
                //spring security的过滤器链
        private final List<Filter> additionalFilters;
                
               //因为在FilterChainProxy中request和response被封装到HttpFirewall中,所以我们从这里获取请求信息
        private final FirewalledRequest firewalledRequest;
        
             //spring security的过滤器的长度
              private final int size;
            
           //当前执行到的位置
        private int currentPosition = 0;

        private VirtualFilterChain(FirewalledRequest firewalledRequest,
                FilterChain chain, List<Filter> additionalFilters) {
            this.originalChain = chain;
            this.additionalFilters = additionalFilters;
            this.size = additionalFilters.size();
            this.firewalledRequest = firewalledRequest;
        }

        @Override
        public void doFilter(ServletRequest request, ServletResponse response)
                throws IOException, ServletException {
                        //表示spring security的过滤器全部执行完成,那么可以执行spring的application context 中的其他的过滤器链了
            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);
            }
        }
    }

4 FilterChainProxydoFilter方法

我们知道FilterChainProxy已经被注册到application context中,那么就会被DelegatingFilterProxy执行到自己的doFilter()方法,然而先没必要想这么多,就把FilterChainProxy当成我们在web.xml中定义的一个Filter就行,当有请求进来就会去执行doFilter方法

@Override
    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();

            chain.doFilter(fwRequest, fwResponse);

            return;
        }
               VirtualFilterChain vfc = new VirtualFilterChain(fwRequest, chain, filters);
        vfc.doFilter(fwRequest, fwResponse);
    }
VirtualFilterChain vfc = new VirtualFilterChain(fwRequest, chain, filters);
vfc.doFilter(fwRequest, fwResponse);

5.总结

这个类还是比较简单和清晰明了的。没有晦涩的继承关系。到此为止,我们已经了解到了spring security 的一个请求过来为什么会去穿透我们的过滤器,可以说对于spring security的启动,spring security filter chain的组建,我们基本已经了解完成,最后,在默认情况下进行调试,我们看一下我们的默认的过滤器有哪些,也顺便结束这篇文章吧.

默认配置下的过滤器
上一篇 下一篇

猜你喜欢

热点阅读