spring security 源码学习(四)SecurityFilterChain
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> configurers = getConfigurers();
for (SecurityConfigurer configurer : configurers) {
configurer.init((B) this);
}
for (SecurityConfigurer 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, 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()).and()(12)
.logout();(13)
// @formatter:on
ClassLoader classLoader = this.context.getClassLoader();
List defaultHttpConfigurers =
SpringFactoriesLoader.loadFactories(AbstractHttpConfigurer.class, classLoader);
for(AbstractHttpConfigurer configurer : defaultHttpConfigurers) {
http.apply(configurer);
}
}
configure(http);
return http;
}
我们拿其中一个来看看。就拿开头的http.csrf();
public CsrfConfigurercsrf() throws Exception { ApplicationContext context = getContext(); return getOrApply(new CsrfConfigurer (context)); }
private> C getOrApply( C configurer) throws Exception { C existingConfig = (C) getConfigurer(configurer.getClass()); if (existingConfig != null) { return existingConfig; } return apply(configurer); }
public> C apply(C configurer) throws Exception { configurer.addObjectPostProcessor(objectPostProcessor); configurer.setBuilder((B) this); add(configurer); return configurer; }
private> void add(C configurer) throws Exception { Assert.notNull(configurer, "configurer cannot be null"); Class<? extends SecurityConfigurer > clazz = (Class<? extends SecurityConfigurer >) configurer .getClass(); synchronized (configurers) { if (buildState.isConfigured()) { throw new IllegalStateException("Cannot apply " + configurer + " to already built object"); } List > configs = allowConfigurersOfSameType ? this.configurers .get(clazz) : null; if (configs == null) { configs = new ArrayList >(1); } configs.add(configurer); this.configurers.put(clazz, configs); if (buildState.isInitializing()) { this.configurersAddedInInitializing.add(configurer); } } }
从上面的一连串的方法可以看出来,http.csrf()将new出来的CsrfConfigurer
private final LinkedHashMap>, List >> configurers = new LinkedHashMap >, List >>();
也就是加入到了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, Listfilters) { logger.info("Creating filter chain: " + requestMatcher + ", " + filters); this.requestMatcher = requestMatcher; this.filters = new ArrayList (filters); }
List
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();
}