先了解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<SecurityConfigurer<O, B>> configurers = getConfigurers(); for (SecurityConfigurer<O, B> 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<Object> objectPostProcessor,
@Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers)//1
throws Exception {
this.webSecurity = objectPostProcessor.postProcess(new WebSecurity(objectPostProcessor));
webSecurityConfigurers.sort(AnnotationAwareOrderComparator.INSTANCE);//2
Integer previousOrder = null;
Object previousConfig = null;
for (SecurityConfigurer<Filter, WebSecurity> config : webSecurityConfigurers) {
Integer order = AnnotationAwareOrderComparator.lookupOrder(config);
previousOrder = order;
previousConfig = config;
}//3
for (SecurityConfigurer<Filter, WebSecurity> webSecurityConfigurer : webSecurityConfigurers) {
this.webSecurity.apply(webSecurityConfigurer);
}//4
this.webSecurityConfigurers = webSecurityConfigurers;
}
- 首先看配有注明
@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(List<WebSecurityCustomizer> webSecurityCustomizers) { 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(); List<SecurityFilterChain> securityFilterChains = new ArrayList<>(chainSize); List<RequestMatcherEntry<List<WebInvocationPrivilegeEvaluator>>> 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大致默认启动流程源码分析就结束了
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)