上一篇文章中,接触了Spring Security并写了一个简单的实例,初次接触毕竟我们对它还不是特别熟悉。我比较好奇的问题包含两处:
1)配置在web.xml配置的springSecurityFilterChain是如何被加载?
2)配置在applicationContext-security.xml中的标签csrf、form-login、logout是如何被解析的呢?
1)配置在web.xml配置的springSecurityFilterChain是如何被加载?
springmvc+spring security项目中web.xml配置了springSecurityFilterChain
<filter> <filter-name>springSecurityFilterChainfilter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxyfilter-class> <init-param> <param-name>targetFilterLifecycleparam-name> <param-value>trueparam-value> init-param> filter> <filter-mapping> <filter-name>springSecurityFilterChainfilter-name> <url-pattern>/*url-pattern> filter-mapping>
org.springframework.web.filter.DelegatingFilterProxy 只是和其他filter一样,是一个javax.servlet.Filter,它将在web servlet系统启动时:先调用listener(pre )->filter(pre doFilter)->servlet([spring mvc]DispatcherServlet)->filter(after doFilter)->listener(after )
因此项目启动时,会执行DelegatingFilterProxy#doFilter方法
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
// Lazily initialize the delegate if necessary.
Filter delegateToUse = this.delegate;
if (delegateToUse == null) {
synchronized (this.delegateMonitor) {
delegateToUse = this.delegate;
if (delegateToUse == null) {
WebApplicationContext wac = findWebApplicationContext();
if (wac == null) {
throw new IllegalStateException("No WebApplicationContext found: " +
"no ContextLoaderListener or DispatcherServlet registered?");
}
delegateToUse = initDelegate(wac);
}
this.delegate = delegateToUse;
}
}
// Let the delegate perform the actual doFilter operation.
invokeDelegate(delegateToUse, request, response, filterChain);
}
上边filter执行主要负责两个事情:
1)执行initDelegate(wac)方法,初始化delegate对象
因为 DelegatingFilterProxy 类继承于抽象类(springframework的)GenericFilterBean,会在初始化bean时,调用 DelegatingFilterProxy#initFilterBean()
GenericFilterBean的定义:
public abstract class GenericFilterBean implements Filter, BeanNameAware, EnvironmentAware,
EnvironmentCapable, ServletContextAware, InitializingBean, DisposableBean {
// ...
@Override
public void afterPropertiesSet() throws ServletException {
initFilterBean();
}
// ...
protected void initFilterBean() throws ServletException {
}
// ...
}
因为GenericFilterBean实现InitializingBean接口,因此项目启动时,spring容器加载bean后,会执行afterPropertiesSet()方法,之后会调用initFilterBean()方法。
DelegatingFilterProxy#initFilterBean()的定义:
public class DelegatingFilterProxy extends GenericFilterBean {
// ...
@Nullable
private volatile Filter delegate;
// ...
@Override
protected void initFilterBean() throws ServletException {
synchronized (this.delegateMonitor) {
if (this.delegate == null) {
// If no target bean name specified, use filter name.
if (this.targetBeanName == null) {
this.targetBeanName = getFilterName();
}
// Fetch Spring root application context and initialize the delegate early,
// if possible. If the root application context will be started after this
// filter proxy, we'll have to resort to lazy initialization.
WebApplicationContext wac = findWebApplicationContext();
if (wac != null) {
this.delegate = initDelegate(wac);
}
}
}
}
// ...
protected Filter initDelegate(WebApplicationContext wac) throws ServletException {
String targetBeanName = getTargetBeanName();
Assert.state(targetBeanName != null, "No target bean name set");
Filter delegate = wac.getBean(targetBeanName, Filter.class);
if (isTargetFilterLifecycle()) {
delegate.init(getFilterConfig());
}
return delegate;
}
// ...
}
当然,无论targetFilterLifecycle是true还是false,都不会影响springSecurityFilterChain的初始化(无论true还是false,以下截图的结果都一样)。
从上图我们能得出的结论:
1)上边targetBeanName是springSecurityFilterChain,通过调用wac.getBean(targetBeanName, Filter.class);从spring容器中获取到对象的类:org.springframework.security.web.FilterChainProxy;
2)’org.springframework.security.web.FilterChainProxy#filterChains’与’applicationContext-shiro.xml中的
3)’filterChains的个数’与’applicationContext-shiro.xml中的
4)这个 springSecurityFilterChain 的bean是如何初始化,和什么时候放入spring容器的呢?在ContextLoaderListener加载applicationContext-security.xml时,解析配置文件时将springSecurityFilterChain初始化放入容器的,这个问题后边会详细介绍。
2)执行invokeDelegate(…)方法
实际上就是执行FilterChainProxy#doFilter(…)方法
protected void invokeDelegate(
Filter delegate, ServletRequest request, ServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
delegate.doFilter(request, response, filterChain);
}
2)配置在applicationContext-security.xml中的标签csrf、form-login、logout是如何被解析的呢?
applicationContext-security.xml配置
xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:security="http://www.springframework.org/schema/security" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd"> <security:http pattern="/css/**" security="none"/> <security:http auto-config="true" use-expressions="false"> <security:csrf disabled="false"/> <security:intercept-url pattern="/" access="IS_AUTHENTICATED_ANONYMOUSLY"/> <security:intercept-url pattern="/index" access="IS_AUTHENTICATED_ANONYMOUSLY"/> <security:intercept-url pattern="/**" access="ROLE_USER"/> <security:form-login default-target-url="/index" /> <security:logout delete-cookies="JSESSIONID" logout-success-url="/login" logout-url="/logout" /> security:http> <security:authentication-manager> <security:authentication-provider> <security:user-service> <security:user name="admin" password="{noop}adminpwd" authorities="ROLE_USER, ROLE_ADMIN"/> <security:user name="user" password="{noop}userpwd" authorities="ROLE_USER"/> security:user-service> security:authentication-provider> security:authentication-manager> beans>
上边的配置文件是比较简单的spring security配置文件了,在 springmvc(web.xml非注解方式)+spring security 项目中,我们需要清楚一件事:就是web.xml中配置的内容的执行先后顺序。
web.xml配置内容如下:
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Applicationdisplay-name>
<span><</span><span>welcome-file-list</span><span>></span>
<span><</span><span>welcome-file</span><span>></span>/index<span><span>welcome-file</span><span>></span>
<span><span>welcome-file-list</span><span>></span>
<span><</span><span>context-param</span><span>></span>
<span><</span><span>param-name</span><span>></span>contextConfigLocation<span><span>param-name</span><span>></span>
<span><</span><span>param-value</span><span>></span><span>
classpath:applicationContext-base.xml,
classpath:applicationContext-security.xml
</span><span><span>param-value</span><span>></span>
<span><span>context-param</span><span>></span>
<span><</span><span>listener</span><span>></span>
<span><</span><span>listener-class</span><span>></span>org.springframework.web.context.ContextLoaderListener<span><span>listener-class</span><span>></span>
<span><span>listener</span><span>></span>
<span><</span><span>listener</span><span>></span>
<span><</span><span>listener-class</span><span>></span>org.springframework.security.web.session.HttpSessionEventPublisher<span><span>listener-class</span><span>></span>
<span><span>listener</span><span>></span>
<span><</span><span>filter</span><span>></span>
<span><</span><span>filter-name</span><span>></span>springSecurityFilterChain<span><span>filter-name</span><span>></span>
<span><</span><span>filter-class</span><span>></span>org.springframework.web.filter.DelegatingFilterProxy<span><span>filter-class</span><span>></span>
<span><</span><span>init-param</span><span>></span>
<span><</span><span>param-name</span><span>></span>targetFilterLifecycle<span><span>param-name</span><span>></span>
<span><</span><span>param-value</span><span>></span>false<span><span>param-value</span><span>></span>
<span><span>init-param</span><span>></span>
<span><span>filter</span><span>></span>
<span><</span><span>filter-mapping</span><span>></span>
<span><</span><span>filter-name</span><span>></span>springSecurityFilterChain<span><span>filter-name</span><span>></span>
<span><</span><span>url-pattern</span><span>></span>/*<span><span>url-pattern</span><span>></span>
<span><span>filter-mapping</span><span>></span>
<span><</span><span>filter</span><span>></span>
<span><</span><span>filter-name</span><span>></span>multipartFilter<span><span>filter-name</span><span>></span>
<span><</span><span>filter-class</span><span>></span>org.springframework.web.multipart.support.MultipartFilter<span><span>filter-class</span><span>></span>
<span><</span><span>init-param</span><span>></span>
<span><</span><span>param-name</span><span>></span>multipartResolverBeanName<span><span>param-name</span><span>></span>
<span><</span><span>param-value</span><span>></span>multipartResolver<span><span>param-value</span><span>></span>
<span><span>init-param</span><span>></span>
<span><span>filter</span><span>></span>
<span><</span><span>filter-mapping</span><span>></span>
<span><</span><span>filter-name</span><span>></span>multipartFilter<span><span>filter-name</span><span>></span>
<span><</span><span>url-pattern</span><span>></span>/*<span><span>url-pattern</span><span>></span>
<span><span>filter-mapping</span><span>></span>
<span><</span><span>filter</span><span>></span>
<span><</span><span>filter-name</span><span>></span>hiddenHttpMethodFilter<span><span>filter-name</span><span>></span>
<span><</span><span>filter-class</span><span>></span>org.springframework.web.filter.HiddenHttpMethodFilter<span><span>filter-class</span><span>></span>
<span><</span><span>init-param</span><span>></span>
<span><</span><span>param-name</span><span>></span>methodParam<span><span>param-name</span><span>></span>
<span><</span><span>param-value</span><span>></span>_method<span><span>param-value</span><span>></span>
<span><span>init-param</span><span>></span>
<span><span>filter</span><span>></span>
<span><</span><span>filter-mapping</span><span>></span>
<span><</span><span>filter-name</span><span>></span>hiddenHttpMethodFilter<span><span>filter-name</span><span>></span>
<span><</span><span>url-pattern</span><span>></span>/*<span><span>url-pattern</span><span>></span>
<span><span>filter-mapping</span><span>></span>
<span><</span><span>filter</span><span>></span>
<span><</span><span>filter-name</span><span>></span>characterEncodingFilter<span><span>filter-name</span><span>></span>
<span><</span><span>filter-class</span><span>></span>org.springframework.web.filter.CharacterEncodingFilter<span><span>filter-class</span><span>></span>
<span><</span><span>init-param</span><span>></span>
<span><</span><span>param-name</span><span>></span>encoding<span><span>param-name</span><span>></span>
<span><</span><span>param-value</span><span>></span>UTF-8<span><span>param-value</span><span>></span>
<span><span>init-param</span><span>></span>
<span><</span><span>init-param</span><span>></span>
<span><</span><span>param-name</span><span>></span>forceEncoding<span><span>param-name</span><span>></span>
<span><</span><span>param-value</span><span>></span>true<span><span>param-value</span><span>></span>
<span><span>init-param</span><span>></span>
<span><span>filter</span><span>></span>
<span><</span><span>filter-mapping</span><span>></span>
<span><</span><span>filter-name</span><span>></span>characterEncodingFilter<span><span>filter-name</span><span>></span>
<span><</span><span>url-pattern</span><span>></span>/*<span><span>url-pattern</span><span>></span>
<span><span>filter-mapping</span><span>></span>
<span><</span><span>servlet</span><span>></span>
<span><</span><span>servlet-name</span><span>></span>spring-security-01<span><span>servlet-name</span><span>></span>
<span><</span><span>servlet-class</span><span>></span>org.springframework.web.servlet.DispatcherServlet<span><span>servlet-class</span><span>></span>
<span><</span><span>init-param</span><span>></span>
<span><</span><span>param-name</span><span>></span>contextConfigLocation<span><span>param-name</span><span>></span>
<span><</span><span>param-value</span><span>></span>classpath:spring-security-01-servlet.xml<span><span>param-value</span><span>></span>
<span><span>init-param</span><span>></span>
<span><</span><span>load-on-startup</span><span>></span>1<span><span>load-on-startup</span><span>></span>
<span><span>servlet</span><span>></span>
<span><</span><span>servlet-mapping</span><span>></span>
<span><</span><span>servlet-name</span><span>></span>spring-security-01<span><span>servlet-name</span><span>></span>
<span><</span><span>url-pattern</span><span>></span>/<span><span>url-pattern</span><span>></span>
<span><span>servlet-mapping</span><span>></span>
web-app>
配置文件中指定的View Code
有两个spring application context初始化的地方:
1)ContextLoaderListener加载applicationContext-base.xml、applicationContext-security.xml,初始化parent application context;
2)DispatcherServlet加载spring-security-01-servlet.xml,初始化child application context。
注意:
1)web.xml中配置内容加载顺序:
-》listener[pre] -》filter[pre] -》springmvc内部处理 -》filter[after] -》listener[after];2)ContextLoaderListener 加载 applicationContext-security.xml 时,需要先根据标签解析器(SecurityNamespaceHandler)解析xml中配置http、csrf、form-login、logout等标签:
在spring-security项目config模块的src/main/resources/META-INF/spring.handlers文件中配合这这样一行代码:
http\://www.springframework.org/schema/security=org.springframework.security.config.SecurityNamespaceHandler
从这里可以看出来spring security的标签解析器是 org.springframework.security.config.SecurityNamespaceHandler 来处理。
SecurityNamespaceHandler该类接口是:NamespaceHandler
public interface NamespaceHandler {
void init();
@Nullable
BeanDefinition parse(Element element, ParserContext parserContext);
@Nullable
BeanDefinitionHolder decorate(Node source, BeanDefinitionHolder definition, ParserContext parserContext);
}
该接口定义了三个方法:
init方法:用于自定义标签的初始化
parse方法:用于解析标签
decorate方法:用于装饰。
SecurityNamespaceHandler类
在spring-security项目中,加载applicationContext-security.xml中处理xml中配置http、csrf、form-login、logout等(所有xml配置security标签,具体所有标签定义:参考org.springframework.security.config.Elements.java),在处理xml这些标签的最终目的是:
解析xml中配置的bean,并将它们加载到spring-framework上下文,供spring-security、spring-mvc项目使用。
其中在org.springframework.security.config.SecurityNamespaceHandler#init方法完成了标签解析类注册的工作:
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());
}
}
从上边代码可以看出:
HttpSecurityBeanDefinitionParser类
HttpSecurityBeanDefinitionParser的parse方法代码:
@Override
public BeanDefinition parse(Element element, ParserContext pc) {
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(
element.getTagName(), pc.extractSource(element));
pc.pushContainingComponent(compositeDef);
registerFilterChainProxyIfNecessary(pc, pc.extractSource(element));
// Obtain the filter chains and add the new chain to it
// 这里FILTER_CHAINS字符串为:org.springframework.security.filterChains
BeanDefinition listFactoryBean = pc.getRegistry().getBeanDefinition(BeanIds.FILTER_CHAINS);
// 其中sourceList是从spring-security.xsd 文件中读取的:
List filterChains = (List) listFactoryBean.getPropertyValues().getPropertyValue("sourceList").getValue();
filterChains.add(createFilterChain(element, pc));
pc.popAndRegisterContainingComponent();
return null;
}
其中 registerFilterChainProxyIfNecessary()实现代码如下:
static void registerFilterChainProxyIfNecessary(ParserContext pc, Object source) {
if (pc.getRegistry().containsBeanDefinition(BeanIds.FILTER_CHAIN_PROXY)) {
return;
}
// Not already registered, so register the list of filter chains and the
// FilterChainProxy
BeanDefinition listFactoryBean = new RootBeanDefinition(ListFactoryBean.class);
listFactoryBean.getPropertyValues().add("sourceList", new ManagedList());
pc.registerBeanComponent(new BeanComponentDefinition(listFactoryBean, BeanIds.FILTER_CHAINS));
BeanDefinitionBuilder fcpBldr = BeanDefinitionBuilder.rootBeanDefinition(FilterChainProxy.class);
fcpBldr.getRawBeanDefinition().setSource(source);
fcpBldr.addConstructorArgReference(BeanIds.FILTER_CHAINS);
fcpBldr.addPropertyValue("filterChainValidator", new RootBeanDefinition(DefaultFilterChainValidator.class));
BeanDefinition fcpBean = fcpBldr.getBeanDefinition();
pc.registerBeanComponent(new BeanComponentDefinition(fcpBean, BeanIds.FILTER_CHAIN_PROXY));
pc.getRegistry().registerAlias(BeanIds.FILTER_CHAIN_PROXY, BeanIds.SPRING_SECURITY_FILTER_CHAIN);
}
备注:
1)FILTER_CHAIN_PROXY 就是 org.springframework.security.filterChainProxy
2)SPRING_SECURITY_FILTER_CHAIN 就是 springSecurityFilterChain
3)这段代码就是注册bean定义 FilterChainProxy 注册的地方,将bean名称定义为:org.springframework.security.filterChainProxy 和 springSecurityChainFilter(别名)
其中,createFilterChain方法
/** * Creates the {@code SecurityFilterChain} bean from an <http> element. */ private BeanReference createFilterChain(Element element, ParserContext pc) { boolean secured = !OPT_SECURITY_NONE.equals(element.getAttribute(ATT_SECURED)); if (!secured) { 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) { pc.getReaderContext().error( "If you are usingto 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 authenticationProviders = new ManagedList<>(); BeanReference authenticationManager = createAuthenticationManager(element, pc, authenticationProviders); boolean forceAutoConfig = isDefaultHttpConfig(element); HttpConfigurationBuilder httpBldr = new HttpConfigurationBuilder(element, forceAutoConfig, pc, portMapper, portResolver, authenticationManager); 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 unorderedFilterChain = new ArrayList<>(); unorderedFilterChain.addAll(httpBldr.getFilters()); unorderedFilterChain.addAll(authBldr.getFilters()); unorderedFilterChain.addAll(buildCustomFilterList(element, pc)); unorderedFilterChain.sort(new OrderComparator()); checkFilterChainOrder(unorderedFilterChain, pc, pc.extractSource(element)); // The list of filter beans List filterChain = new ManagedList<>(); for (OrderDecorator od : unorderedFilterChain) { filterChain.add(od.bean); } return createSecurityFilterChainBean(element, pc, filterChain); }
此时HttpSecurityBeanDefinitionParser的parse方法,filterChains.add(createFilterChain(element,pc))就是注册各个filter bean定义的代码,通过断点调试可以发现。
1)其中 forceAutoConfig 就是读取,如果auto-config=true,那么在 HttpConfigurationBuilder、AuthenticationConfigBuilder 中会自动加载所有security filter的bean定义。
其中 AuthenticationConfigBuilder 中创建filter BeanDefinition代码:
createAnonymousFilter();
createRememberMeFilter(authenticationManager);
createBasicFilter(authenticationManager);
createFormLoginFilter(sessionStrategy, authenticationManager);
createOpenIDLoginFilter(sessionStrategy, authenticationManager);
createX509Filter(authenticationManager);
createJeeFilter(authenticationManager);
createLogoutFilter();
createLoginPageFilterIfNeeded();
createUserDetailsServiceFactory();
createExceptionTranslationFilter();
HttpConfigurationBuilder 中创建filter BeanDefinition代码:
createCsrfFilter();
createSecurityContextPersistenceFilter();
createSessionManagementFilters();
createWebAsyncManagerFilter();
createRequestCacheFilter();
createServletApiFilter(authenticationManager);
createJaasApiFilter();
createChannelProcessingFilter();
createFilterSecurityInterceptor(authenticationManager);
createAddHeadersFilter();
createCorsFilter();
2)如果在 将会特殊处理,需要注意。
跟踪spring applicationContext中加载bean
从上图解析到的bean就是加载applicationContext-*.xml的配置内容的bean:
1)加载applicationContext-base.xml的相关bean定义:
其中前边的
loginController
indexController
org.springframework.context.annotation.internalConfigurationAnnotationProcessor // 处理 @Configuration 注解
org.springframework.context.annotation.internalAutowiredAnnotationProcessor // 处理 @Autowired、@Value、@Inject 注解
org.springframework.context.annotation.internalCommonAnnotationProcessor // 处理 @PostConstruct、@PreDestroy、@Resource、@WebServiceRef
org.springframework.context.event.internalEventListenerProcessor // 处理 @EventListener 注解
org.springframework.context.event.internalEventListenerFactory
multipartResolver // 定义的文件上传解析器 bean
这些都是在加载applicationContext-base.xml时,加载的相关bean定义。
上边org.springframework.context的bean定义在 spring-context-5.2.0.RELEASE-sources.jar!/org/springframework/context/annotation/AnnotationConfigUtils.java中。
其中定义的各个bean的对应的BeanPostProcessor类:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor 对应的类 org.springframework.context.annotation.ConfigurationClassPostProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor 对应的类 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor 对应的类 org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
org.springframework.context.annotation.internalPersistenceAnnotationProcessor 对应的类 org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor
org.springframework.context.event.internalEventListenerProcessor 对应的类 org.springframework.context.event.EventListenerMethodProcessor
org.springframework.context.event.internalEventListenerFactory 对应的类 org.springframework.context.event.DefaultEventListenerFactory
2)加载applicationContext-security.xml的相关bean定义:
8 = "org.springframework.security.filterChains"
9 = "org.springframework.security.filterChainProxy"
10 = "org.springframework.security.web.DefaultSecurityFilterChain#0"
11 = "org.springframework.security.web.PortMapperImpl#0"
12 = "org.springframework.security.web.PortResolverImpl#0"
13 = "org.springframework.security.config.authentication.AuthenticationManagerFactoryBean#0"
14 = "org.springframework.security.authentication.ProviderManager#0"
15 = "requestDataValueProcessor"
16 = "org.springframework.security.web.csrf.LazyCsrfTokenRepository#0"
17 = "org.springframework.security.web.context.HttpSessionSecurityContextRepository#0"
18 = "org.springframework.security.core.session.SessionRegistryImpl#0"
19 = "org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy#0"
20 = "org.springframework.security.web.savedrequest.HttpSessionRequestCache#0"
21 = "org.springframework.security.config.http.HttpConfigurationBuilder$SecurityContextHolderAwareRequestFilterBeanFactory#0"
22 = "org.springframework.security.config.http.HttpConfigurationBuilder$RoleVoterBeanFactory#0"
23 = "org.springframework.security.access.vote.AffirmativeBased#0"
24 = "org.springframework.security.web.access.intercept.FilterSecurityInterceptor#0"
25 = "org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator#0"
26 = "org.springframework.security.authentication.AnonymousAuthenticationProvider#0"
27 = "org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint#0"
28 = "org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter#0"
29 = "org.springframework.security.userDetailsServiceFactory"
30 = "org.springframework.security.web.DefaultSecurityFilterChain#1"
31 = "bCryptPasswordEncoder"
32 = "org.springframework.security.provisioning.InMemoryUserDetailsManager#0"
33 = "org.springframework.security.authentication.dao.DaoAuthenticationProvider#0"
34 = "org.springframework.security.authentication.DefaultAuthenticationEventPublisher#0"
35 = "org.springframework.security.authenticationManager"
Original: https://www.cnblogs.com/yy3b2007com/p/12194142.html
Author: cctext
Title: Java-Security(二):如何初始化springSecurityFilterChain(FilterChainProxy)
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/537853/
转载文章受原作者版权保护。转载请注明原作者出处!