您的位置:首页 > 编程语言 > Java开发

Spring Security3源码分析(17)-Filter链排序分析

2014-09-11 11:59 381 查看
通过前面Spring Security提供的各种Filter的分析,大体上知道每个Filter具体的用途了。 
Spring Security一共提供了20个Filter,我目前只分析了13个(如果http的auto-config="true",那默认的filter列表都包含在这13个里面了),另外7个在后面的源码分析中碰到时会逐个讲解。 
在分析http标签时,已经提到filter排序的问题了,但是没有深入。 

现在再回头看filter是如何排序的。下面的代码片段截取自HttpSecurityBeanDefinitionParser类, 

Java代码  


//定义未排序filter集合。该集合中的对象为OrderDecorator实例。  

List<OrderDecorator> unorderedFilterChain = new ArrayList<OrderDecorator>();  

//添加http、认证相关的filter集合  

unorderedFilterChain.addAll(httpBldr.getFilters());  

unorderedFilterChain.addAll(authBldr.getFilters());  

//定义RequestCacheAwareFilter过滤器,并添加到unorderedFilterChain中  

BeanDefinition requestCacheAwareFilter = new RootBeanDefinition(RequestCacheAwareFilter.class);  

requestCacheAwareFilter.getPropertyValues().addPropertyValue("requestCache", authBldr.getRequestCache());  

unorderedFilterChain.add(new OrderDecorator(requestCacheAwareFilter, REQUEST_CACHE_FILTER));  

//添加自定义filter  

unorderedFilterChain.addAll(buildCustomFilterList(element, pc));  

//根据排序规则进行排序  

Collections.sort(unorderedFilterChain, new OrderComparator());  

//检查每个filter与前一个filter的位置是否相同  

 //这里的检查主要是防止自定义filter直接配置position属性,造成与默认的filter产生order冲突  

checkFilterChainOrder(unorderedFilterChain, pc, source);  

//重新定义filterChain,把经过排序的filter依次添加到filterChain集合中  

List<BeanMetadataElement> filterChain = new ManagedList<BeanMetadataElement>();  

  

for (OrderDecorator od : unorderedFilterChain) {  

    filterChain.add(od.bean);  

}  

细心的同学会发现httpBldr.getFilters()、authBldr.getFilters()两个方法返回的就是OrderDecorator对象的集合列表。并且OrderDecorator对象已经将filter与SecurityFilters中的order关联了起来 

Java代码  


unorderedFilterChain.addAll(httpBldr.getFilters());  

unorderedFilterChain.addAll(authBldr.getFilters());  

顺便看一下创建自定义过滤器部分 

Java代码  


List<OrderDecorator> buildCustomFilterList(Element element, ParserContext pc) {  

    List<Element> customFilterElts = DomUtils.getChildElementsByTagName(element, Elements.CUSTOM_FILTER);  

    List<OrderDecorator> customFilters = new ArrayList<OrderDecorator>();  

  

    final String ATT_AFTER = "after";  

    final String ATT_BEFORE = "before";  

    final String ATT_POSITION = "position";  

    //循环自定义标签列表custom-filter  

    for (Element elt: customFilterElts) {  

        String after = elt.getAttribute(ATT_AFTER);  

        String before = elt.getAttribute(ATT_BEFORE);  

        String position = elt.getAttribute(ATT_POSITION);  

  

        String ref = elt.getAttribute(ATT_REF);  

  

        if (!StringUtils.hasText(ref)) {  

            pc.getReaderContext().error("The '" + ATT_REF + "' attribute must be supplied", pc.extractSource(elt));  

        }  

  

        RuntimeBeanReference bean = new RuntimeBeanReference(ref);  

  

        if(WebConfigUtils.countNonEmpty(new String[] {after, before, position}) != 1) {  

            pc.getReaderContext().error("A single '" + ATT_AFTER + "', '" + ATT_BEFORE + "', or '" +  

                    ATT_POSITION + "' attribute must be supplied", pc.extractSource(elt));  

        }  

        //如果指定了position,直接将filter与order产生关联关系  

        if (StringUtils.hasText(position)) {  

            customFilters.add(new OrderDecorator(bean, SecurityFilters.valueOf(position)));  

        //如果指定了after,将filter与after值加一产生关联关系  

        } else if (StringUtils.hasText(after)) {  

            SecurityFilters order = SecurityFilters.valueOf(after);  

            if (order == SecurityFilters.LAST) {  

                customFilters.add(new OrderDecorator(bean, SecurityFilters.LAST));  

            } else {  

                customFilters.add(new OrderDecorator(bean, order.getOrder() + 1));  

            }  

        //如果指定了before,将filter与before-1产生关联关系  

        } else if (StringUtils.hasText(before)) {  

            SecurityFilters order = SecurityFilters.valueOf(before);  

            if (order == SecurityFilters.FIRST) {  

                customFilters.add(new OrderDecorator(bean, SecurityFilters.FIRST));  

            } else {  

                customFilters.add(new OrderDecorator(bean, order.getOrder() - 1));  

            }  

        }  

    }  

  

    return customFilters;  

}  

这里用到三个重要的与排序相关的类及枚举,分别是OrderDecorator、OrderComparator以及SecurityFilters枚举 
首先看SecurityFilters枚举定义 

Java代码  


enum SecurityFilters {  

    FIRST (Integer.MIN_VALUE),  

    //order=100  

    CHANNEL_FILTER,  

    //order=200  

    CONCURRENT_SESSION_FILTER,  

    //依次递增……  

    SECURITY_CONTEXT_FILTER,  

    LOGOUT_FILTER,  

    X509_FILTER,  

    PRE_AUTH_FILTER,  

    CAS_FILTER,  

    FORM_LOGIN_FILTER,  

    OPENID_FILTER,  

    LOGIN_PAGE_FILTER,  

    DIGEST_AUTH_FILTER,  

    BASIC_AUTH_FILTER,  

    REQUEST_CACHE_FILTER,  

    SERVLET_API_SUPPORT_FILTER,  

    REMEMBER_ME_FILTER,  

    ANONYMOUS_FILTER,  

    SESSION_MANAGEMENT_FILTER,  

    EXCEPTION_TRANSLATION_FILTER,  

    FILTER_SECURITY_INTERCEPTOR,  

    SWITCH_USER_FILTER,  

    LAST (Integer.MAX_VALUE);  

    //这里设置100,主要给自定义过滤器提供after、before的预留位置  

    //也就是说,在某个默认的过滤器前后只能自定义99个过滤器,虽然可能性几乎为0  

    private static final int INTERVAL = 100;  

    private final int order;  

    //返回的order值=序号*间隔100  

    private SecurityFilters() {  

        order = ordinal() * INTERVAL;  

    }  

  

    private SecurityFilters(int order) {  

        this.order = order;  

    }  

    //主要通过该方法返回Filter的位置  

    public int getOrder() {  

       return order;  

    }  

}  

由此可见,该类维护了Spring Security中每个filter的顺序 

接着看OrderDecorator类。这个类实现org.springframework.core.Ordered接口 

Java代码  


class OrderDecorator implements Ordered {  

    BeanMetadataElement bean;  

    int order;  

    //构造函数传递两个参数1.bean定义;2.filter在链中的位置  

    public OrderDecorator(BeanMetadataElement bean, SecurityFilters filterOrder) {  

        this.bean = bean;  

        this.order = filterOrder.getOrder();  

    }  

  

    public OrderDecorator(BeanMetadataElement bean, int order) {  

        this.bean = bean;  

        this.order = order;  

    }  

    //实现接口方法getOrder  

    public int getOrder() {  

        return order;  

    }  

  

    public String toString() {  

        return bean + ", order = " + order;  

    }  

}  

OrderComparator类的路径是org.springframework.core.OrderComparator,实际上是spring core包的一个比较器,可以顺便看下OrderComparator源码。下面截取的只是部分核心代码 

Java代码  


public int compare(Object o1, Object o2) {  

    boolean p1 = (o1 instanceof PriorityOrdered);  

    boolean p2 = (o2 instanceof PriorityOrdered);  

    if (p1 && !p2) {  

        return -1;  

    }  

    else if (p2 && !p1) {  

        return 1;  

    }  

    //前面几行代码主要针对PriorityOrdered,这里不做分析  

  

                     //分别获取Ordered接口实现类的getOrder方法得到order值  

    int i1 = getOrder(o1);  

    int i2 = getOrder(o2);  

                  //对得到的order进行比较  

    return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;  

}  

         //获取Ordered接口的实现类,获取getOrder值  

protected int getOrder(Object obj) {  

    return (obj instanceof Ordered ? ((Ordered) obj).getOrder() : Ordered.LOWEST_PRECEDENCE);  

}  

通过以上的分析,可以总结如下 

1.由SecurityFilters维持位置order 

2.由OrderDecorator维持filter与order的对应关系 

3.由OrderComparator负责比较OrderDecorator的先后顺序 

附上默认的过滤器顺序列表 
order过滤器名称
100ChannelProcessingFilter
200ConcurrentSessionFilter
300SecurityContextPersistenceFilter
400LogoutFilter
500X509AuthenticationFilter
600RequestHeaderAuthenticationFilter
700CasAuthenticationFilter
800UsernamePasswordAuthenticationFilter
900OpenIDAuthenticationFilter
1000DefaultLoginPageGeneratingFilter
1100DigestAuthenticationFilter
1200BasicAuthenticationFilter
1300RequestCacheAwareFilter
1400SecurityContextHolderAwareRequestFilter
1500RememberMeAuthenticationFilter
1600AnonymousAuthenticationFilter
1700SessionManagementFilter
1800ExceptionTranslationFilter
1900FilterSecurityInterceptor
2000SwitchUserFilter
以上标注红色的都已经分析完毕
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Filter链排序分析