收藏私塾在线
 

欢迎您来到私塾在线网!   

请登录! 

免费注册 


zhang的笔记
状态: 离线
人气:5086785
访问用户量:4227
笔记经验:
总积分:261656
级别:VIP5
搜索本笔记
ta的交流分类
ta的交流主题贴(544)
ta的所有交流贴(1049)
ta的全部笔记
全部笔记(255)
未分类笔记(1)
Java Web(9)
并发实践(1)
课程问题(0)
Java(22)
架构(1)
缓存(5)
JavaEE(0)
JVM(12)
跟我学spring3(68)
Spring Sec……(43)
Spring 3.x……(25)
Spring Sec……(20)
跟开涛学Spring……(17)
深入剖析Spring……(18)
性能调优(10)
前端(2)
Tomcat源码解读(1)
spring sec……(0)
存档
2014-01(7)
2013-12(10)
2012-10(4)
2012-09(2)
2012-08(31)
2012-07(10)
2012-06(5)
2012-05(41)
2012-04(3)
2012-03(41)
2012-02(54)
2011-11(17)
2011-10(30)

2012-05-10 16:09:42
Filter链排序分析——Spring Security3源码分析
浏览(8432)|评论(0)   交流分类:Java|笔记分类: Spring Sec……

通过前面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 过滤器名称
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


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

 

 

 http://sishuok.com/forum/blogPost/list/0/4311.html

 

转载自【http://dead-knight.iteye.com/blog/1520080

作者博客:http://dead-knight.iteye.com/

精品视频课程推荐

Java数据结构和算法精讲版
本课程专注于数据结构和算法的内容,使用Java来进行代码示例,不空洞的讲解概念和理论,重点放在代码的实现和示例上。 从零开始、全面系统、成体系的讲解数据结构和基本算法,循序渐进的讲述构建软件系统所常见的数据结构和算法。

研磨设计模式——跟着cc学设计系列视频教程
本视频课程是北京Java私塾原创精品书籍《研磨设计模式》一书的配套学习视频,由《研磨设计模式》的第一作者CC录制 课程目标:全面、系统的掌握GoF设计模式的知识,达到可以在实际项目开发中运用的能力 技术要点:如何实现可配置、如何实现缓存以及缓存的管理、如何实现用缓存来控制多实例的创建、如何实现参数化工厂、 如何实现可扩展工厂、如何实现原型管理器、如何实现Java的静态代理和动态代理、如何实现多线程处理队列请求、 如何实现命令的参数化配置、可撤销的操作、宏命令、队列请求和日志请求、如何实现翻页迭代、如何检测环状结构、 如何实现通用的增删改查、如何模拟工作流来处理流程、如何实现简单又通用的XML读取、如何实现模拟AOP的功能......

深入浅出学Shrio视频教程
内容概述:Shiro是目前最热门、最易用、功能超强大的Java权限管理框架,强烈推荐,每个项目都必备的权限管理技术!通过本课程,你将从零开始直到彻底掌握Shiro的相关开发知识,达到可以进行实际项目开发的能力。包括:权限管理基础、Shiro入门、配置、身份认证、授权、Realms、Session管理、和Spring的集成、Web、Cache等众多开发细节技术 技术要点:源码级分析Shiro的授权过程、自定义开发Realm、多个Realms的开发配置、自定义开发AuthenticationStrategy、自定义开发自定义SessionDAO、和Struts2+Spring3的集成(包括修正struts2的bug)、Shiro和SpringMVC+Spring3的集成、包装使用其他的Cache框架、缓存数据同步更新的解决方案等等实际开发中常用的内容

高级软件架构师实战培训阶段一
内容概述:本课程专注于构建:高可扩展性、高性能、大数据量、高并发、分布式的系统架构。 从零开始、全面系统、成体系的软件架构课程,循序渐进的讲述构建上述系统架构所需要的各种技术知识和技能。
技术要点: 1:构建基本的业务功能块,基于Maven+Git+Spring mvc+spring+mybatis+ehcache+mysql+X-gen代码生成
 2:高扩展性的分布式体系架构(基于Nginx+Varnish+Memcache+ActiveMQ)
 3:NoSQL的合理使用和架构优化(基于MongoDB)
 4:分布式文件存储和架构优化(基于MogileFS)

Weblogic实战视频教程
WebLogic基础知识:WebLogic基本概念、正确安装WebLogic、建域、应用部署于JDBC选择、对WebLogic的监控和日志查看、集群的高可用性;课程目标:彻底掌握WebLogic的基本概念,在理解基本概念的基础上做到正确的安装WebLogic,根据不同的需求创建域,合理选择应用部署和JDBC配置。熟练掌握WebLogic的console监控,了解各种性能和运行指标,以及对监控结果的分析,运用集群的高可用性,对集群架设。

浏览(8432)|评论(0)   交流分类:Java|笔记分类: Spring Sec……

评论(0)
请登录后评论 登录

关于我们 | 联系我们 | 用户协议 | 私塾在线服务协议 | 版权声明 | 隐私保护

版权所有 Copyright(C)2009-2012 私塾在线学习网