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

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

现在再回头看filter是如何排序的。下面的代码片段截取自HttpSecurityBeanDefinitionParser类, 
Java代码   收藏代码
  1. //定义未排序filter集合。该集合中的对象为OrderDecorator实例。  
  2. List<OrderDecorator> unorderedFilterChain = new ArrayList<OrderDecorator>();  
  3. //添加http、认证相关的filter集合  
  4. unorderedFilterChain.addAll(httpBldr.getFilters());  
  5. unorderedFilterChain.addAll(authBldr.getFilters());  
  6. //定义RequestCacheAwareFilter过滤器,并添加到unorderedFilterChain中  
  7. BeanDefinition requestCacheAwareFilter = new RootBeanDefinition(RequestCacheAwareFilter.class);  
  8. requestCacheAwareFilter.getPropertyValues().addPropertyValue("requestCache", authBldr.getRequestCache());  
  9. unorderedFilterChain.add(new OrderDecorator(requestCacheAwareFilter, REQUEST_CACHE_FILTER));  
  10. //添加自定义filter  
  11. unorderedFilterChain.addAll(buildCustomFilterList(element, pc));  
  12. //根据排序规则进行排序  
  13. Collections.sort(unorderedFilterChain, new OrderComparator());  
  14. //检查每个filter与前一个filter的位置是否相同  
  15.  //这里的检查主要是防止自定义filter直接配置position属性,造成与默认的filter产生order冲突  
  16. checkFilterChainOrder(unorderedFilterChain, pc, source);  
  17. //重新定义filterChain,把经过排序的filter依次添加到filterChain集合中  
  18. List<BeanMetadataElement> filterChain = new ManagedList<BeanMetadataElement>();  
  19.   
  20. for (OrderDecorator od : unorderedFilterChain) {  
  21.     filterChain.add(od.bean);  
  22. }  

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


顺便看一下创建自定义过滤器部分 
Java代码   收藏代码
  1. List<OrderDecorator> buildCustomFilterList(Element element, ParserContext pc) {  
  2.     List<Element> customFilterElts = DomUtils.getChildElementsByTagName(element, Elements.CUSTOM_FILTER);  
  3.     List<OrderDecorator> customFilters = new ArrayList<OrderDecorator>();  
  4.   
  5.     final String ATT_AFTER = "after";  
  6.     final String ATT_BEFORE = "before";  
  7.     final String ATT_POSITION = "position";  
  8.     //循环自定义标签列表custom-filter  
  9.     for (Element elt: customFilterElts) {  
  10.         String after = elt.getAttribute(ATT_AFTER);  
  11.         String before = elt.getAttribute(ATT_BEFORE);  
  12.         String position = elt.getAttribute(ATT_POSITION);  
  13.   
  14.         String ref = elt.getAttribute(ATT_REF);  
  15.   
  16.         if (!StringUtils.hasText(ref)) {  
  17.             pc.getReaderContext().error("The '" + ATT_REF + "' attribute must be supplied", pc.extractSource(elt));  
  18.         }  
  19.   
  20.         RuntimeBeanReference bean = new RuntimeBeanReference(ref);  
  21.   
  22.         if(WebConfigUtils.countNonEmpty(new String[] {after, before, position}) != 1) {  
  23.             pc.getReaderContext().error("A single '" + ATT_AFTER + "', '" + ATT_BEFORE + "', or '" +  
  24.                     ATT_POSITION + "' attribute must be supplied", pc.extractSource(elt));  
  25.         }  
  26.         //如果指定了position,直接将filter与order产生关联关系  
  27.         if (StringUtils.hasText(position)) {  
  28.             customFilters.add(new OrderDecorator(bean, SecurityFilters.valueOf(position)));  
  29.         //如果指定了after,将filter与after值加一产生关联关系  
  30.         } else if (StringUtils.hasText(after)) {  
  31.             SecurityFilters order = SecurityFilters.valueOf(after);  
  32.             if (order == SecurityFilters.LAST) {  
  33.                 customFilters.add(new OrderDecorator(bean, SecurityFilters.LAST));  
  34.             } else {  
  35.                 customFilters.add(new OrderDecorator(bean, order.getOrder() + 1));  
  36.             }  
  37.         //如果指定了before,将filter与before-1产生关联关系  
  38.         } else if (StringUtils.hasText(before)) {  
  39.             SecurityFilters order = SecurityFilters.valueOf(before);  
  40.             if (order == SecurityFilters.FIRST) {  
  41.                 customFilters.add(new OrderDecorator(bean, SecurityFilters.FIRST));  
  42.             } else {  
  43.                 customFilters.add(new OrderDecorator(bean, order.getOrder() - 1));  
  44.             }  
  45.         }  
  46.     }  
  47.   
  48.     return customFilters;  
  49. }  


这里用到三个重要的与排序相关的类及枚举,分别是OrderDecorator、OrderComparator以及SecurityFilters枚举 
首先看SecurityFilters枚举定义 
Java代码   收藏代码
  1. enum SecurityFilters {  
  2.     FIRST (Integer.MIN_VALUE),  
  3.     //order=100  
  4.     CHANNEL_FILTER,  
  5.     //order=200  
  6.     CONCURRENT_SESSION_FILTER,  
  7.     //依次递增……  
  8.     SECURITY_CONTEXT_FILTER,  
  9.     LOGOUT_FILTER,  
  10.     X509_FILTER,  
  11.     PRE_AUTH_FILTER,  
  12.     CAS_FILTER,  
  13.     FORM_LOGIN_FILTER,  
  14.     OPENID_FILTER,  
  15.     LOGIN_PAGE_FILTER,  
  16.     DIGEST_AUTH_FILTER,  
  17.     BASIC_AUTH_FILTER,  
  18.     REQUEST_CACHE_FILTER,  
  19.     SERVLET_API_SUPPORT_FILTER,  
  20.     REMEMBER_ME_FILTER,  
  21.     ANONYMOUS_FILTER,  
  22.     SESSION_MANAGEMENT_FILTER,  
  23.     EXCEPTION_TRANSLATION_FILTER,  
  24.     FILTER_SECURITY_INTERCEPTOR,  
  25.     SWITCH_USER_FILTER,  
  26.     LAST (Integer.MAX_VALUE);  
  27.     //这里设置100,主要给自定义过滤器提供after、before的预留位置  
  28.     //也就是说,在某个默认的过滤器前后只能自定义99个过滤器,虽然可能性几乎为0  
  29.     private static final int INTERVAL = 100;  
  30.     private final int order;  
  31.     //返回的order值=序号*间隔100  
  32.     private SecurityFilters() {  
  33.         order = ordinal() * INTERVAL;  
  34.     }  
  35.   
  36.     private SecurityFilters(int order) {  
  37.         this.order = order;  
  38.     }  
  39.     //主要通过该方法返回Filter的位置  
  40.     public int getOrder() {  
  41.        return order;  
  42.     }  
  43. }  

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

接着看OrderDecorator类。这个类实现org.springframework.core.Ordered接口 
Java代码   收藏代码
  1. class OrderDecorator implements Ordered {  
  2.     BeanMetadataElement bean;  
  3.     int order;  
  4.     //构造函数传递两个参数1.bean定义;2.filter在链中的位置  
  5.     public OrderDecorator(BeanMetadataElement bean, SecurityFilters filterOrder) {  
  6.         this.bean = bean;  
  7.         this.order = filterOrder.getOrder();  
  8.     }  
  9.   
  10.     public OrderDecorator(BeanMetadataElement bean, int order) {  
  11.         this.bean = bean;  
  12.         this.order = order;  
  13.     }  
  14.     //实现接口方法getOrder  
  15.     public int getOrder() {  
  16.         return order;  
  17.     }  
  18.   
  19.     public String toString() {  
  20.         return bean + ", order = " + order;  
  21.     }  
  22. }  

OrderComparator类的路径是org.springframework.core.OrderComparator,实际上是spring core包的一个比较器,可以顺便看下OrderComparator源码。下面截取的只是部分核心代码 
Java代码   收藏代码
  1. public int compare(Object o1, Object o2) {  
  2.     boolean p1 = (o1 instanceof PriorityOrdered);  
  3.     boolean p2 = (o2 instanceof PriorityOrdered);  
  4.     if (p1 && !p2) {  
  5.         return -1;  
  6.     }  
  7.     else if (p2 && !p1) {  
  8.         return 1;  
  9.     }  
  10.     //前面几行代码主要针对PriorityOrdered,这里不做分析  
  11.   
  12.                      //分别获取Ordered接口实现类的getOrder方法得到order值  
  13.     int i1 = getOrder(o1);  
  14.     int i2 = getOrder(o2);  
  15.                   //对得到的order进行比较  
  16.     return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;  
  17. }  
  18.          //获取Ordered接口的实现类,获取getOrder值  
  19. protected int getOrder(Object obj) {  
  20.     return (obj instanceof Ordered ? ((Ordered) obj).getOrder() : Ordered.LOWEST_PRECEDENCE);  
  21. }  


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

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

以上标注红色的都已经分析完毕
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值