用户可以创建一个WebSecurityConfigurerAdapter的子类,然后在configure方法中配置认证授权条件,这些条件会转化为一个个的SecurityConfigurer的子类,他们会被放到一个名为configurers的hashmap里,在AbstractConfiguredSecurityBuilder的configure方法中会获取configurers中的所有SecurityConfigurer,然后依次调用他们的configure方法。这些configure方法主要还是注册filter到filterchain。
我们从@EnableWebSecurity注解说起
@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value = { java.lang.annotation.ElementType.TYPE })
@Documented
@Import({ WebSecurityConfiguration.class,
SpringWebMvcImportSelector.class })
@EnableGlobalAuthentication
@Configuration
public @interface EnableWebSecurity
这里有个很重要的类WebSecurityConfiguration他里面有个方法:
@Autowired(required = false)
public void setFilterChainProxySecurityConfigurer(
ObjectPostProcessor<Object> objectPostProcessor,
@Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers)
throws Exception {
这个方法会把spring上下文中的实现了SecurityConfigurer的所有的bean都放到一个webSecurity对象的configurers中,其实一般我们做自定义配置时是要实现一个WebSecurityConfigurerAdapter的子类,WebSecurityConfigurerAdapter实现了SecurityConfigurer接口,所以我们定义的类会被放到webSecurity对象的configurers中,后面分析会用到。
再来看WebSecurityConfiguration的另一个方法
@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
public Filter springSecurityFilterChain() throws Exception
这里AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME=“springSecurityFilterChain”
也即是这里通过springSecurityFilterChain方法向spring上下文添加了一个名为springSecurityFilterChain的bean,后面分析会用到
接着看springSecurityFilterChain这个方法他调用了webSecurity.build()->doBuild()->init()
@SuppressWarnings("unchecked")
private void init() throws Exception {
Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();
for (SecurityConfigurer<O, B> configurer : configurers) {
configurer.init((B) this);
}
可以看到getConfigurers会获取到我们之前提到的configurers,然后这里就是一次调用configurer的init()方法,注意这里的(B) this是webSecurity对象,后续还会出现httpSecurity对象,所以比较混乱,一般我们实现WebSecurityConfigurerAdapter的子类不会覆盖init方法,所以这里就用的WebSecurityConfigurerAdapter的init方法。
public void init(final WebSecurity web) throws Exception {
final HttpSecurity http = getHttp();
web.addSecurityFilterChainBuilder(http).postBuildAction(new Runnable() {
public void run() {
FilterSecurityInterceptor securityInterceptor = http
.getSharedObject(FilterSecurityInterceptor.class);
web.securityInterceptor(securityInterceptor);
}
});
}