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

在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<BeanReference> authenticationProviders = new ManagedList<BeanReference>();  
  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.   
  71.         List<OrderDecorator> unorderedFilterChain = new ArrayList<OrderDecorator>();  
  72.         //向FilterChain链中添加filters  
  73.         unorderedFilterChain.addAll(httpBldr.getFilters());  
  74.         unorderedFilterChain.addAll(authBldr.getFilters());  
  75.         //向ProviderManager中添加provider  
  76.         authenticationProviders.addAll(authBldr.getProviders());  
  77.   
  78.         BeanDefinition requestCacheAwareFilter = new RootBeanDefinition(RequestCacheAwareFilter.class);  
  79.         requestCacheAwareFilter.getPropertyValues().addPropertyValue(“requestCache”, authBldr.getRequestCache());  
  80.         unorderedFilterChain.add(new OrderDecorator(requestCacheAwareFilter, REQUEST_CACHE_FILTER));  
  81.         //添加自定义的Filter,也就是custom-filter标签定义的Filter  
  82.         unorderedFilterChain.addAll(buildCustomFilterList(element, pc));  
  83.         //对FilterChian链中的Filter进行排序,排序规则参见SecurityFilters枚举类  
  84.         Collections.sort(unorderedFilterChain, new OrderComparator());  
  85.         checkFilterChainOrder(unorderedFilterChain, pc, source);  
  86.   
  87.         List<BeanMetadataElement> filterChain = new ManagedList<BeanMetadataElement>();  
  88.   
  89.         for (OrderDecorator od : unorderedFilterChain) {  
  90.             filterChain.add(od.bean);  
  91.         }  
  92.   
  93.         ManagedMap<BeanDefinition, List<BeanMetadataElement>> filterChainMap = httpBldr.getFilterChainMap();  
  94.         BeanDefinition universalMatch = new RootBeanDefinition(String.class);  
  95.         universalMatch.getConstructorArgumentValues().addGenericArgumentValue(matcher.getUniversalMatchPattern());  
  96.         filterChainMap.put(universalMatch, filterChain);  
  97.         //构造FilterChainProxy的Bean  
  98.         registerFilterChainProxy(pc, filterChainMap, matcher, source);  
  99.   
  100.         pc.popAndRegisterContainingComponent();  
  101.         return null;  
  102.     }  

至此,大概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的数据结构。

    原文作者:Spring Boot
    原文地址: https://blog.csdn.net/benjamin_whx/article/details/39204571
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞