Spring Security3源码分析(2)-http标签解析

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

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

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

在FilterChainProxy初始化的过程中,大概描述了标签解析的一些步骤,但不够详细

Xml代码

  1. <**http auto-config=“true”>**
  2. <**remember-me key=“workweb” token-validity-seconds=“3600” data-source-ref=“dataSource”/>**
  3. <**form-login login-page=“/login.jsp”/>**
  4. <**logout logout-success-url=“/login.jsp”/>**
  5. <**intercept-url pattern=“/*” access=“ROLE_USER”/>**
  6. </**http**>

http标签的解析过程由类org.springframework.security.config.http.HttpSecurityBeanDefinitionParser解析。

Java代码

  1. public BeanDefinition parse(Element element, ParserContext pc) {
  2. CompositeComponentDefinition compositeDef =
  3. new CompositeComponentDefinition(element.getTagName(), pc.extractSource(element));
  4. pc.pushContainingComponent(compositeDef);
  5. final Object source = pc.extractSource(element);
  6. //portMapperName、matcher主要提供给SSL相关类使用
  7. final String portMapperName = createPortMapper(element, pc);
  8. final UrlMatcher matcher = createUrlMatcher(element);
  9. //http标签构造器,该构造函数中对intercept-url、create-session子标签
  10. //进行了预处理,并将所有的intercept-url信息放到List中。
  11. HttpConfigurationBuilder httpBldr = new HttpConfigurationBuilder(element, pc, matcher, portMapperName);
  12. //处理List中的intercept-url信息(如pattern、filters),并将结果放到
  13. //Map集合filterChainMap中
  14. httpBldr.parseInterceptUrlsForEmptyFilterChains();
  15. //创建过滤器SecurityContextPersistenceFilter
  16. httpBldr.createSecurityContextPersistenceFilter();
  17. //创建过滤器SessionManagementFilter
  18. httpBldr.createSessionManagementFilters();
  19. //新建一个空的provider集合
  20. ManagedList authenticationProviders = new ManagedList();
  21. //通过空的provider集合产生一个ProviderManager的bean定义
  22. BeanReference authenticationManager = createAuthenticationManager(element, pc, authenticationProviders, null);
  23. //创建过滤器SecurityContextHolderAwareRequestFilter
  24. httpBldr.createServletApiFilter();
  25. //判断intercept-url标签是否有requires-channel属性,如果有,则创建过滤器
  26. //ChannelProcessingFilter
  27. httpBldr.createChannelProcessingFilter();
  28. //创建过滤器FilterSecurityInterceptor
  29. //这个创建过程比较复杂,分别为:
  30. //1.需要判断是否使用表达式use-expressions
  31. //2.解析intercept-url中的access等属性
  32. //3.RoleVoter、AffirmativeBased的定义…………
  33. httpBldr.createFilterSecurityInterceptor(authenticationManager);
  34. //下面是与认证有关的过滤器,HttpConfigurationBuilder,
  35. //AuthenticationConfigBuilder将解析的职责进行了分离
  36. AuthenticationConfigBuilder authBldr = new AuthenticationConfigBuilder(element, pc,
  37. httpBldr.isAllowSessionCreation(), portMapperName);
  38. //创建过滤器AnonymousAuthenticationFilter,并且构造了provider:
  39. //AnonymousAuthenticationProvider,供ProviderManager使用
  40. authBldr.createAnonymousFilter();
  41. //判断是否有remember-me标签,如果有,则创建过滤器
  42. //RememberMeAuthenticationFilter,并且构造了provider:
  43. //RememberMeAuthenticationProvider供ProviderManager使用
  44. authBldr.createRememberMeFilter(authenticationManager);
  45. //判断是否有request-cache标签,如果有,则构造ref指明的bean定义
  46. //如果没有,则构造HttpSessionRequestCache缓存
  47. authBldr.createRequestCache();
  48. //创建过滤器BasicAuthenticationFilter
  49. authBldr.createBasicFilter(authenticationManager);
  50. //创建LoginUrlAuthenticationEntryPoint,以及创建过滤器
  51. //UsernamePasswordAuthenticationFilter
  52. authBldr.createFormLoginFilter(httpBldr.getSessionStrategy(), authenticationManager);
  53. //判断是否使用了openid-login,如果有,则构造openId客户端
  54. //org.springframework.security.openid.OpenID4JavaConsumer
  55. authBldr.createOpenIDLoginFilter(httpBldr.getSessionStrategy(), authenticationManager);
  56. //判断是否使用了x509,如果有,则创建过滤器
  57. //X509AuthenticationFilter
  58. authBldr.createX509Filter(authenticationManager);
  59. //判断是否配置了logout,如果有,则创建过滤器LogoutFilter
  60. authBldr.createLogoutFilter();
  61. //判断是否配置login-page属性,如果没有,则创建过滤器
  62. //DefaultLoginPageGeneratingFilter,生成默认登录页面
  63. authBldr.createLoginPageFilterIfNeeded();
  64. //创建UserDetailsServiceInjectionBeanPostProcessor
  65. //动态向x509、openID、rememberme服务注入UserDetailsService
  66. //主要使用了spring的BeanPostProcessor接口功能
  67. authBldr.createUserServiceInjector();
  68. //创建过滤器ExceptionTranslationFilter
  69. authBldr.createExceptionTranslationFilter();
  70. List unorderedFilterChain = new ArrayList();
  71. //向FilterChain链中添加filters
  72. unorderedFilterChain.addAll(httpBldr.getFilters());
  73. unorderedFilterChain.addAll(authBldr.getFilters());
  74. //向ProviderManager中添加provider
  75. authenticationProviders.addAll(authBldr.getProviders());
  76. BeanDefinition requestCacheAwareFilter = new RootBeanDefinition(RequestCacheAwareFilter.class);
  77. requestCacheAwareFilter.getPropertyValues().addPropertyValue(“requestCache”, authBldr.getRequestCache());
  78. unorderedFilterChain.add(new OrderDecorator(requestCacheAwareFilter, REQUEST_CACHE_FILTER));
  79. //添加自定义的Filter,也就是custom-filter标签定义的Filter
  80. unorderedFilterChain.addAll(buildCustomFilterList(element, pc));
  81. //对FilterChian链中的Filter进行排序,排序规则参见SecurityFilters枚举类
  82. Collections.sort(unorderedFilterChain, new OrderComparator());
  83. checkFilterChainOrder(unorderedFilterChain, pc, source);
  84. List filterChain = new ManagedList();
  85. for (OrderDecorator od : unorderedFilterChain) {
  86. filterChain.add(od.bean);
  87. }
  88. ManagedMap<BeanDefinition, List> filterChainMap = httpBldr.getFilterChainMap();
  89. BeanDefinition universalMatch = new RootBeanDefinition(String.class);
  90. universalMatch.getConstructorArgumentValues().addGenericArgumentValue(matcher.getUniversalMatchPattern());
  91. filterChainMap.put(universalMatch, filterChain);
  92. //构造FilterChainProxy的Bean
  93. registerFilterChainProxy(pc, filterChainMap, matcher, source);
  94. pc.popAndRegisterContainingComponent();
  95. return null;
  96. }

至此,大概http标签的解析已经差不多了,虽然每个Filter的BeanDefinition创建过程还没有一一细说,但基本步骤如下:

1.通过Filter的类路径获取BeanDefinitionBuilder对象,如
BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(filterClassName);

2.解析xml标签属性,再通过BeanDefinitionBuilder的addPropertyValue、addPropertyReference等方法设置Filter对应BeanDefinition的属性值、依赖bean

3.注册BeanDefinition。通过
ParserContext.registerBeanComponent(
new BeanComponentDefinition(BeanDefinition,beanId));
完成bean的注册。还可以通过ParserContext.getRegistry().registerAlias
方法注册bean的别名

实际上,标签解析就是构造BeanDefinition,然后注册到bean factory中。而BeanDefinition就是Spring中定义bean的数据结构。


来源:http://ddrv.cn

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

评论 抢沙发

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

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

支付宝扫一扫打赏

微信扫一扫打赏