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

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】

Spring Security3源码分析-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 unorderedFilterChain = new ArrayList();
  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 filterChain = new ManagedList();
  19. for (OrderDecorator od : unorderedFilterChain) {
  20. filterChain.add(od.bean);
  21. }

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

Java代码

  1. unorderedFilterChain.addAll(httpBldr.getFilters());
  2. unorderedFilterChain.addAll(authBldr.getFilters());

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

Java代码

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

这里用到三个重要的与排序相关的类及枚举,分别是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. privatestaticfinalint INTERVAL = 100;
  30. privatefinalint order;
  31. //返回的order值=序号*间隔100
  32. private SecurityFilters() {
  33. order = ordinal() * INTERVAL;
  34. }
  35. private SecurityFilters(int order) {
  36. this.order = order;
  37. }
  38. //主要通过该方法返回Filter的位置
  39. publicint getOrder() {
  40. return order;
  41. }
  42. }

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

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

  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. public OrderDecorator(BeanMetadataElement bean, int order) {
  10. this.bean = bean;
  11. this.order = order;
  12. }
  13. //实现接口方法getOrder
  14. publicint getOrder() {
  15. return order;
  16. }
  17. public String toString() {
  18. return bean + “, order = “ + order;
  19. }
  20. }

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

  1. publicint 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. elseif (p2 && !p1) {
  8. return1;
  9. }
  10. //前面几行代码主要针对PriorityOrdered,这里不做分析
  11. //分别获取Ordered接口实现类的getOrder方法得到order值
  12. int i1 = getOrder(o1);
  13. int i2 = getOrder(o2);
  14. //对得到的order进行比较
  15. return (i1 < i2) ? –1 : (i1 > i2) ? 1 : 0;
  16. }
  17. //获取Ordered接口的实现类,获取getOrder值
  18. protectedint getOrder(Object obj) {
  19. return (obj instanceof Ordered ? ((Ordered) obj).getOrder() : Ordered.LOWEST_PRECEDENCE);
  20. }

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

1.由SecurityFilters维持位置order
2.由OrderDecorator维持filter与order的对应关系
3.由OrderComparator负责比较OrderDecorator的先后顺序

附上默认的过滤器顺序列表

order 过滤器名称
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://ddrv.cn

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » Spring Security3源码分析-Filter链排序分析

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏