先了解spring.factories
spring.factories
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration, org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration, org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration, org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration, org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration,
- SecurityAutoConfiguration是主配置类,我们主要讲解该类
- UserDetailsServiceAutoConfiguration是用于设置默认密码的,它这将会在SecurityAutoConfiguration配置HttpSecurity时配置,所以我们不细讲
- SecurityFilterAutoConfiguration不讲
- 后面两个为OAuth安全,不讲
我们主要分析SecurityAutoConfiguration,它是一个自动配置类,受EnableWebSecurit 的影响,会加载前会先导入HttpSecurityConfiguration和WebSecurityConfiguration
它们作用顺序分别为: HttpSecurityConfiguration配置HttpSecurityConfiguration、WebSecurityConfiguration配置WebSecurity
流程主要也是围绕: 配置HttpSecurity --> 配置默认的基本的SecurityFilterChain --> 配置WebSecurity --> 配置最终的SecurityFilterChain
也可以理解为:如何创建最终的SecurityFilterChain呢 ?
EnableWebSecurity和EnableGlobalAuthentication注解
@Import({ WebSecurityConfiguration.class, SpringWebMvcImportSelector.class, OAuth2ImportSelector.class,
HttpSecurityConfiguration.class })
@EnableGlobalAuthentication
@Configuration
public @interface EnableWebSecurity {}
@Import(AuthenticationConfiguration.class)
@Configuration
public @interface EnableGlobalAuthentication {}
配置HttpSecurity
从HttpSecurityConfiguration开始,该类是HttpSecurity的基本配置类,配置如下:
HttpSecurityConfiguration.java
@Autowired
void setAuthenticationConfiguration(AuthenticationConfiguration authenticationConfiguration) {
this.authenticationConfiguration = authenticationConfiguration;
}//1
@Bean(HTTPSECURITY_BEAN_NAME)
@Scope("prototype")
HttpSecurity httpSecurity() throws Exception {
WebSecurityConfigurerAdapter.LazyPasswordEncoder passwordEncoder = new WebSecurityConfigurerAdapter.LazyPasswordEncoder(
this.context);//2
AuthenticationManagerBuilder authenticationBuilder = new WebSecurityConfigurerAdapter.DefaultPasswordEncoderAuthenticationManagerBuilder(
this.objectPostProcessor, passwordEncoder);//3
authenticationBuilder.parentAuthenticationManager(authenticationManager());//4
HttpSecurity http = new HttpSecurity(this.objectPostProcessor, authenticationBuilder, createSharedObjects());//5
http
.csrf(withDefaults())
.addFilter(new WebAsyncManagerIntegrationFilter())
.exceptionHandling(withDefaults())
.headers(withDefaults())
.sessionManagement(withDefaults())
.securityContext(withDefaults())
.requestCache(withDefaults())
.anonymous(withDefaults())
.servletApi(withDefaults())
.apply(new DefaultLoginPageConfigurer<>());
http.logout(withDefaults());//6
return http;
}
依赖注入一个AuthenticationConfiguration,提前加载前面需要自动配置的AuthenticationConfiguration,
该类创建了三个重要的Bean对象AuthenticationManagerBuild、InitializeUserDetailsBeanManagerConfigurer也就是和InitializeAuthenticationProviderBeanManagerConfigurer
分别用来
- 构建AuthenticationManager
- 用来初始化spring.factories中的UserDetailsServiceAutoConfiguration,它的功能是提供默认的用户名和密码、
- 初始化用户认证管理器(ProviderManager)
创建一个懒密码加载器
创建一个认证管理器构建器
构建一个认证管理器
AuthenticationConfiguration.java
public AuthenticationManager getAuthenticationManager() throws Exception { //... for (GlobalAuthenticationConfigurerAdapter config : this.globalAuthConfigurers) { authBuilder.apply(config); }//1 this.authenticationManager = authBuilder.build();//2 //... return this.authenticationManager; }
构建器使用全局认证配置,也就是前面创建AuthencationConfiguration时提及的
构建认证管理器
直接看最后的doBuild()
AbstractConfiguredSecurityBuilder
protected final O doBuild() throws Exception { synchronized (this.configurers) { this.buildState = BuildState.INITIALIZING; beforeInit();//1 init();//2 this.buildState = BuildState.CONFIGURING; beforeConfigure();//3 configure();//4 this.buildState = BuildState.BUILDING; O result = performBuild();//5 this.buildState = BuildState.BUILT; return result; } }
初始化前操作
初始化配置器
配置前操作
配置配置器,配置器有很多就不多讲了,配置过程如下:
AbstractConfiguredSecurityBuilder
private void configure() throws Exception { Collection> configurers = getConfigurers(); for (SecurityConfigurer configurer : configurers) { configurer.configure((B) this); } } 开始构建
该方法创建并返回PrivideManager
AuthenticationManagerBuilder.java
protected ProviderManager performBuild() throws Exception { ProviderManager providerManager = new ProviderManager(this.authenticationProviders, this.parentAuthenticationManager); return providerManager; }创建HttpSecurity,将之前的Privider注入HttpSecurity中
HttpSecurity配置基本的配置器
配置SecurityFilterChain
默认的HttpSecurity配置完之后,将会开始配置默认的SecurityFilterChain,
我们看SecurityAutoConfiguration导入的SpringBootWebSecurityConfiguration类
SpringBootWebSecurityConfiguration.java
@Configuration(proxyBeanMethods = false)
@ConditionalOnDefaultWebSecurity//1
@ConditionalOnWebApplication(type = Type.SERVLET)
class SpringBootWebSecurityConfiguration {
@Bean
@Order(SecurityProperties.BASIC_AUTH_ORDER)
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated().and().formLogin().and().httpBasic();
return http.build();//2
}
}
该类在满足默认WebSecurity时才会配置,如下:
@Conditional(DefaultWebSecurityCondition.class)//1 public @interface ConditionalOnDefaultWebSecurity {} class DefaultWebSecurityCondition extends AllNestedConditions { DefaultWebSecurityCondition() {super(ConfigurationPhase.REGISTER_BEAN);} @ConditionalOnClass({ SecurityFilterChain.class, HttpSecurity.class }) static class Classes {}//2 @ConditionalOnMissingBean({ WebSecurityConfigurerAdapter.class, SecurityFilterChain.class }) static class Beans {}//3 }
- 满足DefaultWebSecurityCondition条件
- 满足具有SecurityFilterChain.class, HttpSecurity.class两个类
- 满足缺少WebSecurityConfigurerAdapter.class, SecurityFilterChain.class两个Bean,,而默认的Security配置是缺少这两个类的
创建默认基本的SecurityFilterChain,这里创建完成SecurityFilterChain具有十五个基本的Filter:
配置WebSecurity
配置完默认基本的SecurityFilterChain后,将会配置WebSecurity
我们看到WebSecurityConfiguration类
先看它是如何配置WebSecurity的,如下:
WebrSecurityConfiguration.java
@Autowired(required = false) public void setFilterChainProxySecurityConfigurer(ObjectPostProcessor
- 首先看配有注明@Value的形参,该注释获取了之前配置的所有WebSeucurityConfigurer(也就是自定义的WebSecurityConfigurer),在下方它将把配置器全部传给当前创建的WebSecurity,
- 创建WebSecurity
- 排序获取的(自定义的)SecurityConfigurer
- 将获取的(自定义的)SecurityConfigurer配置器传入当前WebSecuirty中,apply使用配置器,自然不用多说
配置最终的FilterChainProxy
配置完WebSecurity,基础的SecurityFilterChain,将配置最终的SecurityFilterChain
WebSecurityConfiguration.java
@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
public Filter springSecurityFilterChain() throws Exception {
if (!hasConfigurers && !hasFilterChain) {
WebSecurityConfigurerAdapter adapter = this.objectObjectPostProcessor
.postProcess(new WebSecurityConfigurerAdapter() {
});
this.webSecurity.apply(adapter);
}//1
for (SecurityFilterChain securityFilterChain : this.securityFilterChains) {
this.webSecurity.addSecurityFilterChainBuilder(() -> securityFilterChain);
for (Filter filter : securityFilterChain.getFilters()) {
if (filter instanceof FilterSecurityInterceptor) {
this.webSecurity.securityInterceptor((FilterSecurityInterceptor) filter);
break;
}
}
}//2
for (WebSecurityCustomizer customizer : this.webSecurityCustomizers) {
customizer.customize(this.webSecurity);
}//3
return this.webSecurity.build();//4
}
如果没有FilterChain则创建FilterChain,无论是自定义还是默认,通常都有FilterChain
WebSecurity设置FilterSecurityInterceptor
配置自定义的WebSecurity,该自定义类需要实现WebSecurityCustomizer接口
WebSecurityConfiguration.java
@Autowired(required = false) void setWebSecurityCustomizers(ListwebSecurityCustomizers) { this.webSecurityCustomizers = webSecurityCustomizers; } 返回最终再经WebSecuriity配置完的SecurityFilterChain(最终版)
buid()方法就不多讲了,之前配置[HttpSecurity](# 配置HttpSecurity)中的AuthenticationConfiguration时也讲过,这里我们主要解析一下不同继承AbstractConfiguredSecurityBuilder的performBuild()方法
WebSecurity.java
@Override protected Filter performBuild() throws Exception { int chainSize = this.ignoredRequests.size() + this.securityFilterChainBuilders.size(); ListsecurityFilterChains = new ArrayList<>(chainSize); List >> requestMatcherPrivilegeEvaluatorsEntries = new ArrayList<>(); for (RequestMatcher ignoredRequest : this.ignoredRequests) { SecurityFilterChain securityFilterChain = new DefaultSecurityFilterChain(ignoredRequest); securityFilterChains.add(securityFilterChain); requestMatcherPrivilegeEvaluatorsEntries .add(getRequestMatcherPrivilegeEvaluatorsEntry(securityFilterChain)); } for (SecurityBuilder extends SecurityFilterChain> securityFilterChainBuilder : this.securityFilterChainBuilders) { SecurityFilterChain securityFilterChain = securityFilterChainBuilder.build(); securityFilterChains.add(securityFilterChain); requestMatcherPrivilegeEvaluatorsEntries .add(getRequestMatcherPrivilegeEvaluatorsEntry(securityFilterChain)); } if (this.privilegeEvaluator == null) { this.privilegeEvaluator = new RequestMatcherDelegatingWebInvocationPrivilegeEvaluator( requestMatcherPrivilegeEvaluatorsEntries); } FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains); if (this.httpFirewall != null) { filterChainProxy.setFirewall(this.httpFirewall); } if (this.requestRejectedHandler != null) { filterChainProxy.setRequestRejectedHandler(this.requestRejectedHandler); } filterChainProxy.afterPropertiesSet(); Filter result = filterChainProxy; this.postBuildAction.run(); return result; } 分析一下可以得出,该方法的功能,就是把默认的SecurityFilterChain中的过滤器和WebSecurity的过滤器,加入新创建的FilterChainProxy中,并返回
完结
至此SpringSecurity大致默认启动流程源码分析就结束了



