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(); }