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 { 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 { @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); } return this .webSecurity.build(); } }
此配置官方解释
WebSecurity用来创建FilterChainProxy,即核心过滤器 springSecurityFilterChain
可以通过继承WebSecurityConfigurerAdapter并将其公开Configuration,或者实现WebSecurityCnfigurer接口并以Configuration,可以对WebSecurity进行自定义。
此配置是在使用EnableWebSecurity时导入的
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 <>()); } }
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 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); return this .http; } @Override public void init (WebSecurity web) throws Exception { HttpSecurity http = getHttp(); web.addSecurityFilterChainBuilder(http).postBuildAction(() -> { FilterSecurityInterceptor securityInterceptor = http.getSharedObject(FilterSecurityInterceptor.class); web.securityInterceptor(securityInterceptor); }); } private void applyDefaultConfiguration (HttpSecurity http) throws Exception { http.csrf(); 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依次执行
3、FilterChainProxy
核心过滤器 springSecurityFilterChain
的类型 FilterChainProxy
,通过WebSecurity构建
这个类继承了GenericFilterBean,这个类实现了Filter接口所以 FilterChainProxy 也是个过滤器。
它是过滤器链的一个代理,真正起作用的是它内部维护的一组 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; ..... }