当前位置:首页 > 开发 > 开源软件 > 正文

Spring Security3源码分析-Filter链排序分析

发表于: 2012-05-09   作者:Dead_knight   来源:转载   浏览次数:
摘要: 通过前面Spring Security提供的各种Filter的分析,大体上知道每个Filter具体的用途了。 Spring Security一共提供了20个Filter,我目前只分析了13个(如果http的auto-config="true",那默认的filter列表都包含在这13个里面了),另外7个在后面的源码分析中碰到时会逐个讲解。 在分析http标签时,已经提到fil
通过前面Spring Security提供的各种Filter的分析,大体上知道每个Filter具体的用途了。
Spring Security一共提供了20个Filter,我目前只分析了13个(如果http的auto-config="true",那默认的filter列表都包含在这13个里面了),另外7个在后面的源码分析中碰到时会逐个讲解。
在分析http标签时,已经提到filter排序的问题了,但是没有深入。

现在再回头看filter是如何排序的。下面的代码片段截取自HttpSecurityBeanDefinitionParser类,
        //定义未排序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关联了起来
        unorderedFilterChain.addAll(httpBldr.getFilters());
        unorderedFilterChain.addAll(authBldr.getFilters());


顺便看一下创建自定义过滤器部分
    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枚举定义
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接口
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源码。下面截取的只是部分核心代码
	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 过滤器名称
100 ChannelProcessingFilter
200 ConcurrentSessionFilter
300 SecurityContextPersistenceFilter
400 LogoutFilter
500 X509AuthenticationFilter
600 RequestHeaderAuthenticationFilter
700 CasAuthenticationFilter
800 UsernamePasswordAuthenticationFilter
900 OpenIDAuthenticationFilter
1000 DefaultLoginPageGeneratingFilter
1100 DigestAuthenticationFilter
1200 BasicAuthenticationFilter
1300 RequestCacheAwareFilter
1400 SecurityContextHolderAwareRequestFilter
1500 RememberMeAuthenticationFilter
1600 AnonymousAuthenticationFilter
1700 SessionManagementFilter
1800 ExceptionTranslationFilter
1900 FilterSecurityInterceptor
2000 SwitchUserFilter

以上标注红色的都已经分析完毕

Spring Security3源码分析-Filter链排序分析

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
前面分析了FilterChainProxy执行过程,也对常用的filter逐一深入介绍了,但似乎忽略了Spring Securi
前面分析了FilterChainProxy执行过程,也对常用的filter逐一深入介绍了,但似乎忽略了Spring Securi
前面分析了FilterChainProxy执行过程,也对常用的filter逐一深入介绍了,但似乎忽略了Spring Securi
前面分析了FilterChainProxy执行过程,也对常用的filter逐一深入介绍了,但似乎忽略了Spring Securi
前面分析了FilterChainProxy执行过程,也对常用的filter逐一深入介绍了,但似乎忽略了Spring Securi
软件开发经历了从汇编语言到高级语言和从过程化编程到面向对象编程;前者是为了提高开发效率,而后
软件开发经历了从汇编语言到高级语言和从过程化编程到面向对象编程;前者是为了提高开发效率,而后
一、AOP介绍 举个例子来说明一下吧!现在系统中有很多的业务方法,如上传产品信息、修改产品信息、
软件开发经历了从汇编语言到高级语言和从过程化编程到面向对象编程;前者是为了提高开发效率,而后
做课程设计时,写了一个排序的算法包,可用来分析常用的几种排序算法的交换,比较和移动等的次数。
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号