SecurityFilterChain是Spring security真正执行认证授权的类。这个类初始化是从HttpSecurity的build而来。也就是上篇文章securityFilterChainBuilder.build()处得来。为了省去翻到上一篇文章,我把必要的代码和类图传送过来。
for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : securityFilterChainBuilders) {
securityFilterChains.add(securityFilterChainBuilder.build());(1)
}

所以securityFilterChainBuilder.build()就是AbstractSecurityBuilder的build方法
public final O build() throws Exception {
if (this.building.compareAndSet(false, true)) {
this.object = doBuild();
return this.object;
}
throw new AlreadyBuiltException("This object has already been built");
}
doBuild()就是我们的老演员了,上篇文章也说过的模版方法
protected final O doBuild() throws Exception {
synchronized (configurers) {
buildState = BuildState.INITIALIZING;
beforeInit();
init();
buildState = BuildState.CONFIGURING;
beforeConfigure();
configure();
buildState = BuildState.BUILDING;
O result = performBuild();
buildState = BuildState.BUILT;
return result;
}
}
同样的,让我们从init()开始
private void init() throws Exception {
Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();
for (SecurityConfigurer<O, B> configurer : configurers) {
configurer.init((B) this);
}
for (SecurityConfigurer<O, B> configurer : configurersAddedInInitializing) {
configurer.init((B) this);
}
}
这里的getConfigurers()是从哪来的呢?答案就在Httpsecurity初始化的时候,同样,我们把上一篇文章中getHttp()方法考过来。
protected final HttpSecurity getHttp() throws Exception {
if (http != null) {
return http;
}
DefaultAuthenticationEventPublisher eventPublisher = objectPostProcessor
.postProcess(new DefaultAuthenticationEventPublisher());
localConfigureAuthenticationBldr.authenticationEventPublisher(eventPublisher);
AuthenticationManager authenticationManager = authenticationManager();(1)
authenticationBuilder.parentAuthenticationManager(authenticationManager);
Map<Class<? extends Object>, Object> sharedObjects = createSharedObjects();
http = new HttpSecurity(objectPostProcessor, authenticationBuilder,
sharedObjects);(2)
if (!disableDefaults) {
// @formatter:off
http
.csrf().and()(3)
.addFilter(new WebAsyncManagerIntegrationFilter())(4)
.exceptionHandling().and()(5)
.headers().and()(6)
.sessionManagement().and()(7)
.securityContext().and()(8)
.requestCache().and()(9)
.anonymous().and()(10)
.servletApi().and()(11)
.apply(new DefaultLoginPageConfigurer<HttpSecurity>()).and()(12)
.logout();(13)
// @formatter:on
ClassLoader classLoader = this.context.getClassLoader();
List<AbstractHttpConfigurer> defaultHttpConfigurers =
SpringFactoriesLoader.loadFactories(AbstractHttpConfigurer.class, classLoader);
for(AbstractHttpConfigurer configurer : defaultHttpConfigurers) {
http.apply(configurer);
}
}
configure(http);
return http;
}
我们拿其中一个来看看。就拿开头的http.csrf();
public CsrfConfigurer<HttpSecurity> csrf() throws Exception {
ApplicationContext context = getContext();
return getOrApply(new CsrfConfigurer<HttpSecurity>(context));
}
private <C extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity>> C getOrApply(
C configurer) throws Exception {
C existingConfig = (C) getConfigurer(configurer.getClass());
if (existingConfig != null) {
return existingConfig;
}
return apply(configurer);
}
public <C extends SecurityConfigurerAdapter<O, B>> C apply(C configurer)
throws Exception {
configurer.addObjectPostProcessor(objectPostProcessor);
configurer.setBuilder((B) this);
add(configurer);
return configurer;
}
private <C extends SecurityConfigurer<O, B>> void add(C configurer) throws Exception {
Assert.notNull(configurer, "configurer cannot be null");
Class<? extends SecurityConfigurer<O, B>> clazz = (Class<? extends SecurityConfigurer<O, B>>) configurer
.getClass();
synchronized (configurers) {
if (buildState.isConfigured()) {
throw new IllegalStateException("Cannot apply " + configurer
+ " to already built object");
}
List<SecurityConfigurer<O, B>> configs = allowConfigurersOfSameType ? this.configurers
.get(clazz) : null;
if (configs == null) {
configs = new ArrayList<SecurityConfigurer<O, B>>(1);
}
configs.add(configurer);
this.configurers.put(clazz, configs);
if (buildState.isInitializing()) {
this.configurersAddedInInitializing.add(configurer);
}
}
}
从上面的一连串的方法可以看出来,http.csrf()将new出来的CsrfConfigurer<HttpSecurity>(context)加入到了
private final LinkedHashMap<Class<? extends SecurityConfigurer<O, B>>, List<SecurityConfigurer<O, B>>> configurers = new LinkedHashMap<Class<? extends SecurityConfigurer<O, B>>, List<SecurityConfigurer<O, B>>>();
也就是加入到了getConfigurers返回的List中。
这里每个Configurer实际的init和config我们针对每个不同的Configurer都做一个专题走访,这里提供传送门
| configure | filter | 简述 |
| SecurityContextConfigurer |
SecurityContextPersistenceFilter
|
|
最后我们看下performBuild方法
@Override
protected DefaultSecurityFilterChain performBuild() throws Exception {
Collections.sort(filters, comparator);
return new DefaultSecurityFilterChain(requestMatcher, filters);
}
这里倒是比较简单,对上面的filters拍了个序,然后new出了DefaultSecurityFilterChain,这里注意下DefaultSecurityFilterChain构造器的两个参数
public DefaultSecurityFilterChain(RequestMatcher requestMatcher, List<Filter> filters) {
logger.info("Creating filter chain: " + requestMatcher + ", " + filters);
this.requestMatcher = requestMatcher;
this.filters = new ArrayList<Filter>(filters);
}
List<Filter> filters我们在上面已经分析过了,他们具体的形成我们后面细说,RequestMatcher requestMatcher这个参数的作用也是异常的大,他根据uri进行match判断,觉得了是否用这个HttpSecurity形成的FilterChain来对请求做处理。默认情况是
private RequestMatcher requestMatcher = AnyRequestMatcher.INSTANCE;
也就是所有的我们都走认证,如果想要做配置,就可以在上一篇文章中讲的在配置中override这个方法
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.anyRequest().authenticated()
.antMatchers("/aaa").authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}