在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
//动态向x50九、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的数据结构。