SpringSecurity 原理初探(二)

SpringSecutity的核心就是构建一个名字为 springSecurityFilterChain 的过滤器Bean,它的类型是 FilterChainProxy

1、@EnableWebSecurity

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
//将配置中的组件导入容器
@Import({ WebSecurityConfiguration.class, SpringWebMvcImportSelector.class, OAuth2ImportSelector.class,
HttpSecurityConfiguration.class })
@EnableGlobalAuthentication
@Configuration
public @interface EnableWebSecurity {

/**
* Controls debugging support for Spring Security. Default is false.
* @return if true, enables debug support with Spring Security
*/
boolean debug() default false;

}

WebSecurityConfiguration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@Configuration(proxyBeanMethods = false)
public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAware {

//往容器中放了一个springSecurityFilterChain过滤器链Bean 类型为FilterChainProxy
@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
public Filter springSecurityFilterChain() throws Exception {
boolean hasConfigurers = this.webSecurityConfigurers != null && !this.webSecurityConfigurers.isEmpty();
boolean hasFilterChain = !this.securityFilterChains.isEmpty();
Assert.state(!(hasConfigurers && hasFilterChain),
"Found WebSecurityConfigurerAdapter as well as SecurityFilterChain. Please select just one.");
if (!hasConfigurers && !hasFilterChain) {
WebSecurityConfigurerAdapter adapter = this.objectObjectPostProcessor
.postProcess(new WebSecurityConfigurerAdapter() {
});
this.webSecurity.apply(adapter);
}
for (SecurityFilterChain securityFilterChain : this.securityFilterChains) {
this.webSecurity.addSecurityFilterChainBuilder(() -> securityFilterChain);
for (Filter filter : securityFilterChain.getFilters()) {
if (filter instanceof FilterSecurityInterceptor) {
this.webSecurity.securityInterceptor((FilterSecurityInterceptor) filter);
break;
}
}
}
for (WebSecurityCustomizer customizer : this.webSecurityCustomizers) {
customizer.customize(this.webSecurity);
}

//通过webSecurity构建
return this.webSecurity.build();
}

}

此配置官方解释

  1. WebSecurity用来创建FilterChainProxy,即核心过滤器 springSecurityFilterChain

  2. 可以通过继承WebSecurityConfigurerAdapter并将其公开Configuration,或者实现WebSecurityCnfigurer接口并以Configuration,可以对WebSecurity进行自定义。

  3. 此配置是在使用EnableWebSecurity时导入的

  4. HttpSecurity 的构建目标只是 FilterChainProxy 对象中一组 SecurityFilterChain 的一个

2、自定义SpringSecurity

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Configuration
@EnableWebSecurity
public class SecurityConfigOne extends WebSecurityConfigurerAdapter {


//创建过滤器链
@Override
protected void configure(HttpSecurity http) throws Exception {
http
//访问请求的授权规则配置
.authorizeRequests()
.anyRequest().authenticated()
.and().formLogin(); //在未经身份验证的用户访问受保护的资源时自动重定向到登录页面

}


@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("admin")
.password("{noop}123456")
.authorities(new ArrayList<>());
}
}

2.1、WebSecurityConfigurerAdapter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
//hou
protected final HttpSecurity getHttp() throws Exception {
if (this.http != null) {
return this.http;
}
//获取身份认证事件发布对象
AuthenticationEventPublisher eventPublisher = getAuthenticationEventPublisher();
this.localConfigureAuthenticationBldr.authenticationEventPublisher(eventPublisher);
//身份验证管理器
AuthenticationManager authenticationManager = authenticationManager();
this.authenticationBuilder.parentAuthenticationManager(authenticationManager);
Map<Class<?>, Object> sharedObjects = createSharedObjects();
this.http = new HttpSecurity(this.objectPostProcessor, this.authenticationBuilder, sharedObjects);
if (!this.disableDefaults) {
applyDefaultConfiguration(this.http);
ClassLoader classLoader = this.context.getClassLoader();
List<AbstractHttpConfigurer> defaultHttpConfigurers = SpringFactoriesLoader
.loadFactories(AbstractHttpConfigurer.class, classLoader);
for (AbstractHttpConfigurer configurer : defaultHttpConfigurers) {
this.http.apply(configurer);
}
}
configure(this.http); //调用自己重写过后的configure方法
return this.http;
}

@Override
public void init(WebSecurity web) throws Exception {
HttpSecurity http = getHttp();
//创建SecurityFilterChain实例
web.addSecurityFilterChainBuilder(http).postBuildAction(() -> {
FilterSecurityInterceptor securityInterceptor = http.getSharedObject(FilterSecurityInterceptor.class);
web.securityInterceptor(securityInterceptor);
});
}



//每执行一个方法后,会根据这个方法创建一个过滤器
//默认配置,可以在重写的configure方法中通过disable关闭
private void applyDefaultConfiguration(HttpSecurity http) throws Exception {
http.csrf(); //调用这个方法后会创建一个CsrfFilter过滤器
http.addFilter(new WebAsyncManagerIntegrationFilter());
http.exceptionHandling();
http.headers();
http.sessionManagement();
http.securityContext();
http.requestCache();
http.anonymous();
http.servletApi();
http.apply(new DefaultLoginPageConfigurer<>());
http.logout();
}

//默认配置,如果没有重写则调用此方法
protected void configure(HttpSecurity http) throws Exception {
this.logger.debug("Using default configure(HttpSecurity). "
+ "If subclassed this will potentially override subclass configure(HttpSecurity).");
http.authorizeRequests((requests) -> requests.anyRequest().authenticated());
http.formLogin();
http.httpBasic();
}

当没有重写configure方法或者没有自定义SpringSecurity,默认会生成15个filter会交给FilterChainProxy依次执行

image-20231030000520252

3、FilterChainProxy

核心过滤器 springSecurityFilterChain 的类型 FilterChainProxy,通过WebSecurity构建

  1. 这个类继承了GenericFilterBean,这个类实现了Filter接口所以 FilterChainProxy 也是个过滤器。
  2. 它是过滤器链的一个代理,真正起作用的是它内部维护的一组 SecurityFilterChain 过滤器链,SecurityFilterChain 是一个接口,有个默认实现类 DefaultSecurityFilterChain ,实现类里面主要是一组 URL 和一组 过滤器
1
2
3
4
5
6
7
8
public final class DefaultSecurityFilterChain implements SecurityFilterChain {
private static final Log logger = LogFactory.getLog(DefaultSecurityFilterChain.class);
private final RequestMatcher requestMatcher;
private final List<Filter> filters;

.....

}