标签:rac bdd epo 单例 with uil init decorator nod
这个需要从DelegatingFilterProxy类说起,从名字来看是个代理类,也就是说它并不是filter的实际实现,而且他从属于 org.springframework.web.filter这个包,也就是说它没有和springsecurity强绑定,其实从他的dofilter方法不难发现它是通过bean名去springcontext中取出相应的filter bean,然后执行dofilter。为啥不直接写成filter呢,可能设计者就是想设计的灵活吧,根据配置的bean名从springcontext取出。DelegatingFilterProxy需要在web.xml里配置,和其他filter没有区别
<!-- SpringSecurity需要的filter --><filter> <filter-name>spring-security</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <init-param> <param-name>targetBeanName</param-name> <param-value>abcFilterChain</param-value> </init-param></filter><filter-mapping> <filter-name>spring-security</filter-name> <url-pattern>/*</url-pattern></filter-mapping>
这里init-param里的param-name和param-value可以不用配置,只要配置filter-name为bean名也可以,程序中找不到param-name参数就会使用filter-name,一般我们使用springsecurity时,直接将filter-name写为springSecurityFilterChain,因为springsecurity在解析spring-security.xml时会默认注册springSecurityFilterChain这个bean。这个得从标签解析说起,Spring Security的标签解析由org.springframework.security.config.SecurityNamespaceHandler来处理。该类实现接口:NamespaceHandler,Spring中自定义标签都要实现该接口,这个接口有三个方法init、parse、decorate,其中init用于自定义标签的初始化,parse用于解析标签,decorate用于装饰。SecurityNamespaceHandler类的init方法完成了标签解析类的注册工作。打开SecurityNamespaceHandler源码。
public void init() {
loadParsers();}
private void loadParsers() {
// Parsers
parsers.put(Elements.LDAP_PROVIDER, new LdapProviderBeanDefinitionParser());
parsers.put(Elements.LDAP_SERVER, new LdapServerBeanDefinitionParser());
parsers.put(Elements.LDAP_USER_SERVICE, new LdapUserServiceBeanDefinitionParser());
parsers.put(Elements.USER_SERVICE, new UserServiceBeanDefinitionParser());
parsers.put(Elements.JDBC_USER_SERVICE, new JdbcUserServiceBeanDefinitionParser());
parsers.put(Elements.AUTHENTICATION_PROVIDER, new AuthenticationProviderBeanDefinitionParser());
parsers.put(Elements.GLOBAL_METHOD_SECURITY, new GlobalMethodSecurityBeanDefinitionParser());
parsers.put(Elements.AUTHENTICATION_MANAGER, new AuthenticationManagerBeanDefinitionParser());
parsers.put(Elements.METHOD_SECURITY_METADATA_SOURCE, new MethodSecurityMetadataSourceBeanDefinitionParser());
// Only load the web-namespace parsers if the web classes are available
if (ClassUtils.isPresent(FILTER_CHAIN_PROXY_CLASSNAME, getClass().getClassLoader())) {
parsers.put(Elements.DEBUG, new DebugBeanDefinitionParser());
parsers.put(Elements.HTTP, new HttpSecurityBeanDefinitionParser());
parsers.put(Elements.HTTP_FIREWALL, new HttpFirewallBeanDefinitionParser());
parsers.put(Elements.FILTER_SECURITY_METADATA_SOURCE, new FilterInvocationSecurityMetadataSourceParser());
parsers.put(Elements.FILTER_CHAIN, new FilterChainBeanDefinitionParser());
filterChainMapBDD = new FilterChainMapBeanDefinitionDecorator();
}
if (ClassUtils.isPresent(MESSAGE_CLASSNAME, getClass().getClassLoader())) {
parsers.put(Elements.WEBSOCKET_MESSAGE_BROKER, new WebSocketMessageBrokerSecurityBeanDefinitionParser());
}
}上面可以看出SecurityNamespaceHandler类的init方法完成了标签解析类的注册工作,并且http的标签解析类注册代码为:
parsers.put(Elements.HTTP, new HttpSecurityBeanDefinitionParser());
在该类中parse方法
public BeanDefinition parse(Element element, ParserContext pc) {
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), pc.extractSource(element));
pc.pushContainingComponent(compositeDef);
// 这里创建了listFactoryBean实例和springSecurityFilterChain实例,详解移步3.2.1
registerFilterChainProxyIfNecessary(pc, pc.extractSource(element));
// 获取listFactoryBean实例
BeanDefinition listFactoryBean = pc.getRegistry().getBeanDefinition(BeanIds.FILTER_CHAINS);
List<BeanReference> filterChains = (List<BeanReference>) listFactoryBean.getPropertyValues().getPropertyValue("sourceList").getValue();
// 创建过滤器链代码,注意这里添加的filter会在FilterChainProxy的doFilterInternal中使用。
filterChains.add(createFilterChain(element, pc));
pc.popAndRegisterContainingComponent();
return null;}首先看registerFilterChainProxyIfNecessary方法
static void registerFilterChainProxyIfNecessary(ParserContext pc, Object source) {
// 判断是否已经注册了FILTER_CHAIN_PROXY,若已经注册则直接返回,也就是说用户可以自定义BeanIds.FILTER_CHAIN_PROXY bean,如果那样的话,系统就不自动
注册那个bean了
if (pc.getRegistry().containsBeanDefinition(BeanIds.FILTER_CHAIN_PROXY)) {
return;
}
// 注册ListFactoryBean,也就是把BeanIds.FILTER_CHAINS和一个beandefinition绑定,springcontext里都是这样保持一个map,然后调用getbean时会根据
bean名找到beandefinition,然后根据beanDefinition创建bean实例,当然如果web.xml里配置了ContextLoaderListener,他会在tomcat启动后初始化springcontext
并创建单例的bean,这个具体参见ContextLoaderListener的分析。
BeanDefinition listFactoryBean = new RootBeanDefinition(ListFactoryBean.class);
listFactoryBean.getPropertyValues().add("sourceList", new ManagedList());
pc.registerBeanComponent(new BeanComponentDefinition(listFactoryBean, BeanIds.FILTER_CHAINS));
// 注册FilterChainProxy
BeanDefinitionBuilder fcpBldr = BeanDefinitionBuilder.rootBeanDefinition(FilterChainProxy.class);
fcpBldr.getRawBeanDefinition().setSource(source);
fcpBldr.addConstructorArgReference(BeanIds.FILTER_CHAINS);//这里将BeanIds.FILTER_CHAINS设置为FilterChainProxy类的初始化参数
//查看FilterChainProxy类的doFilterInternal->getFilters会用到这个参数,也就是filterchains,之后会执行这个chain里的filter,
//那么这个chain里的filter从哪注册呢,可以看看上面parse方法里的倒数第三句。
fcpBldr.addPropertyValue("filterChainValidator", new RootBeanDefinition(DefaultFilterChainValidator.class));
BeanDefinition fcpBean = fcpBldr.getBeanDefinition();
pc.registerBeanComponent(new BeanComponentDefinition(fcpBean, BeanIds.FILTER_CHAIN_PROXY));
// 此处为FILTER_CHAIN_PROXY取别名为springSecurityFilterChain
pc.getRegistry().registerAlias(BeanIds.FILTER_CHAIN_PROXY, BeanIds.SPRING_SECURITY_FILTER_CHAIN);}接着看createFilterChain
// 创建过滤器链的代码
private BeanReference createFilterChain(Element element, ParserContext pc) {
// 判断是否需要SpringSecurity拦截
boolean secured = !OPT_SECURITY_NONE.equals(element.getAttribute(ATT_SECURED));
if (!secured) {
// 如果没pattern并且配置request-matcher-ref为空 添加错误信息
if (!StringUtils.hasText(element.getAttribute(ATT_PATH_PATTERN)) && !StringUtils.hasText(ATT_REQUEST_MATCHER_REF)) {
pc.getReaderContext().error("The '" + ATT_SECURED + "' attribute must be used in combination with" + " the '" + ATT_PATH_PATTERN + "' or '" + ATT_REQUEST_MATCHER_REF + "' attributes.", pc.extractSource(element));
}
for (int n = 0; n < element.getChildNodes().getLength(); n++) {
if (element.getChildNodes().item(n) instanceof Element) {
// 如果element有子节点并且instanceofElement 添加错误信息
pc.getReaderContext().error("If you are using <http> to define an unsecured pattern, " + "it cannot contain child elements.", pc.extractSource(element));
}
}
return createSecurityFilterChainBean(element, pc, Collections.emptyList());
}
final BeanReference portMapper = createPortMapper(element, pc);
final BeanReference portResolver = createPortResolver(portMapper, pc);
ManagedList<BeanReference> authenticationProviders = new ManagedList<BeanReference>();
BeanReference authenticationManager = createAuthenticationManager(element, pc, authenticationProviders);
boolean forceAutoConfig = isDefaultHttpConfig(element);
// HttpConfigurationBuilder创建过滤器链,详情移步3.2.2.1
HttpConfigurationBuilder httpBldr = new HttpConfigurationBuilder(element, forceAutoConfig, pc, portMapper, portResolver, authenticationManager);
// AuthenticationConfigBuilder创建过滤器链,详情移步3.2.2.2
AuthenticationConfigBuilder authBldr = new AuthenticationConfigBuilder(element, forceAutoConfig, pc, httpBldr.getSessionCreationPolicy(), httpBldr.getRequestCache(), authenticationManager, httpBldr.getSessionStrategy(), portMapper, portResolver, httpBldr.getCsrfLogoutHandler());
httpBldr.setLogoutHandlers(authBldr.getLogoutHandlers());
httpBldr.setEntryPoint(authBldr.getEntryPointBean());
httpBldr.setAccessDeniedHandler(authBldr.getAccessDeniedHandlerBean());
authenticationProviders.addAll(authBldr.getProviders());
List<OrderDecorator> unorderedFilterChain = new ArrayList<OrderDecorator>();
// 添加过滤器到unorderedFilterChain
unorderedFilterChain.addAll(httpBldr.getFilters());
unorderedFilterChain.addAll(authBldr.getFilters());
unorderedFilterChain.addAll(buildCustomFilterList(element, pc));
// 对过滤器链进行排序,详细分析请移步3.2.2.3
Collections.sort(unorderedFilterChain, new OrderComparator());
// 对过滤器链正确性检查
checkFilterChainOrder(unorderedFilterChain, pc, pc.extractSource(element));
// The list of filter beans
List<BeanMetadataElement> filterChain = new ManagedList<BeanMetadataElement>();
for (OrderDecorator od : unorderedFilterChain) {
filterChain.add(od.bean);
}
// 创建过滤器链,详情移步3.2.2.4
return createSecurityFilterChainBean(element, pc, filterChain);}标签:rac bdd epo 单例 with uil init decorator nod
原文地址:http://blog.51cto.com/2839840/2070924