在FilterChainProxy初始化的过程中,大概描述了标签解析的一些步骤,但不够详细
- <http auto-config=“true”>
- <remember-me key=“workweb” token-validity-seconds=“3600” data-source-ref=“dataSource”/>
- <form-login login-page=“/login.jsp”/>
- <logout logout-success-url=“/login.jsp”/>
- <intercept-url pattern=“/*” access=“ROLE_USER”/>
- </http>
http标签的解析过程由类org.springframework.security.config.http.HttpSecurityBeanDefinitionParser解析。
- public BeanDefinition parse(Element element, ParserContext pc) {
- CompositeComponentDefinition compositeDef =
- new CompositeComponentDefinition(element.getTagName(), pc.extractSource(element));
- pc.pushContainingComponent(compositeDef);
- final Object source = pc.extractSource(element);
- //portMapperName、matcher主要提供给SSL相关类使用
- final String portMapperName = createPortMapper(element, pc);
- final UrlMatcher matcher = createUrlMatcher(element);
- //http标签构造器,该构造函数中对intercept-url、create-session子标签
- //进行了预处理,并将所有的intercept-url信息放到List中。
- HttpConfigurationBuilder httpBldr = new HttpConfigurationBuilder(element, pc, matcher, portMapperName);
- //处理List中的intercept-url信息(如pattern、filters),并将结果放到
- //Map集合filterChainMap中
- httpBldr.parseInterceptUrlsForEmptyFilterChains();
- //创建过滤器SecurityContextPersistenceFilter
- httpBldr.createSecurityContextPersistenceFilter();
- //创建过滤器SessionManagementFilter
- httpBldr.createSessionManagementFilters();
- //新建一个空的provider集合
- ManagedList<BeanReference> authenticationProviders = new ManagedList<BeanReference>();
- //通过空的provider集合产生一个ProviderManager的bean定义
- BeanReference authenticationManager = createAuthenticationManager(element, pc, authenticationProviders, null);
- //创建过滤器SecurityContextHolderAwareRequestFilter
- httpBldr.createServletApiFilter();
- //判断intercept-url标签是否有requires-channel属性,如果有,则创建过滤器
- //ChannelProcessingFilter
- httpBldr.createChannelProcessingFilter();
- //创建过滤器FilterSecurityInterceptor
- //这个创建过程比较复杂,分别为:
- //1.需要判断是否使用表达式use-expressions
- //2.解析intercept-url中的access等属性
- //3.RoleVoter、AffirmativeBased的定义…………
- httpBldr.createFilterSecurityInterceptor(authenticationManager);
- //下面是与认证有关的过滤器,HttpConfigurationBuilder,
- //AuthenticationConfigBuilder将解析的职责进行了分离
- AuthenticationConfigBuilder authBldr = new AuthenticationConfigBuilder(element, pc,
- httpBldr.isAllowSessionCreation(), portMapperName);
- //创建过滤器AnonymousAuthenticationFilter,并且构造了provider:
- //AnonymousAuthenticationProvider,供ProviderManager使用
- authBldr.createAnonymousFilter();
- //判断是否有remember-me标签,如果有,则创建过滤器
- //RememberMeAuthenticationFilter,并且构造了provider:
- //RememberMeAuthenticationProvider供ProviderManager使用
- authBldr.createRememberMeFilter(authenticationManager);
- //判断是否有request-cache标签,如果有,则构造ref指明的bean定义
- //如果没有,则构造HttpSessionRequestCache缓存
- authBldr.createRequestCache();
- //创建过滤器BasicAuthenticationFilter
- authBldr.createBasicFilter(authenticationManager);
- //创建LoginUrlAuthenticationEntryPoint,以及创建过滤器
- //UsernamePasswordAuthenticationFilter
- authBldr.createFormLoginFilter(httpBldr.getSessionStrategy(), authenticationManager);
- //判断是否使用了openid-login,如果有,则构造openId客户端
- //org.springframework.security.openid.OpenID4JavaConsumer
- authBldr.createOpenIDLoginFilter(httpBldr.getSessionStrategy(), authenticationManager);
- //判断是否使用了x509,如果有,则创建过滤器
- //X509AuthenticationFilter
- authBldr.createX509Filter(authenticationManager);
- //判断是否配置了logout,如果有,则创建过滤器LogoutFilter
- authBldr.createLogoutFilter();
- //判断是否配置login-page属性,如果没有,则创建过滤器
- //DefaultLoginPageGeneratingFilter,生成默认登录页面
- authBldr.createLoginPageFilterIfNeeded();
- //创建UserDetailsServiceInjectionBeanPostProcessor
- //动态向x509、openID、rememberme服务注入UserDetailsService
- //主要使用了spring的BeanPostProcessor接口功能
- authBldr.createUserServiceInjector();
- //创建过滤器ExceptionTranslationFilter
- authBldr.createExceptionTranslationFilter();
- List<OrderDecorator> unorderedFilterChain = new ArrayList<OrderDecorator>();
- //向FilterChain链中添加filters
- unorderedFilterChain.addAll(httpBldr.getFilters());
- unorderedFilterChain.addAll(authBldr.getFilters());
- //向ProviderManager中添加provider
- authenticationProviders.addAll(authBldr.getProviders());
- BeanDefinition requestCacheAwareFilter = new RootBeanDefinition(RequestCacheAwareFilter.class);
- requestCacheAwareFilter.getPropertyValues().addPropertyValue(“requestCache”, authBldr.getRequestCache());
- unorderedFilterChain.add(new OrderDecorator(requestCacheAwareFilter, REQUEST_CACHE_FILTER));
- //添加自定义的Filter,也就是custom-filter标签定义的Filter
- unorderedFilterChain.addAll(buildCustomFilterList(element, pc));
- //对FilterChian链中的Filter进行排序,排序规则参见SecurityFilters枚举类
- Collections.sort(unorderedFilterChain, new OrderComparator());
- checkFilterChainOrder(unorderedFilterChain, pc, source);
- List<BeanMetadataElement> filterChain = new ManagedList<BeanMetadataElement>();
- for (OrderDecorator od : unorderedFilterChain) {
- filterChain.add(od.bean);
- }
- ManagedMap<BeanDefinition, List<BeanMetadataElement>> filterChainMap = httpBldr.getFilterChainMap();
- BeanDefinition universalMatch = new RootBeanDefinition(String.class);
- universalMatch.getConstructorArgumentValues().addGenericArgumentValue(matcher.getUniversalMatchPattern());
- filterChainMap.put(universalMatch, filterChain);
- //构造FilterChainProxy的Bean
- registerFilterChainProxy(pc, filterChainMap, matcher, source);
- pc.popAndRegisterContainingComponent();
- return null;
- }
至此,大概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的数据结构。