如果你有使用过 Spring Security,我相信你对下面的配置肯定不会陌生:
@Override
protected void configure(final HttpSecurity http) throws Exception {
// @formatter:off
http
.authorizeRequests()
.antMatchers("/css/**,", "index").permitAll()
.mvcMatchers("/user/index").hasRole("USERS")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.failureUrl("/login-error")
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/index");
// @formatter:on
}
这个配置算是最基础的配置,但如果应用业务不复杂,这样的配置已经可以满足应用的安全需求了,它指定了登陆登出的 url,登陆失败的跳转 url,以及资源的安全配置信息。
为什么这样配置就可以了呢?
这个配置我们一般会写在一个叫做 WebSecurityConfigurerAdapter 的继承类里面:
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
...
}
如果我们稍微点进 WebSecurityConfigurerAdapter 看一下,就会知道为什么我们那样简单配置一下就可以了。因为在 WebSecurityConfigurerAdapter 的 getHttp() 方法中已经帮我们做了 11 道默认的 Filter 的配置。我们上面的配置,只是在 11 道默认的 Filter 的基础上再额外增加了三道 Filter,其中有两道在整个 Spring Security 认证与授权过程中最为重要的 Filter:
FilterSecurityInterceptor
.authorizeRequests()
.antMatchers("/css/**,", "index").permitAll()
.mvcMatchers("/user/index").hasRole("USERS")
UsernamePasswordAuthenticationFilter
.formLogin()
.loginPage("/login")
.failureUrl("/login-error")
它们一个完成了认证,一个完成了授权,是 Spring Security 最为核心的两个入口点,要想了解 Spring Security,就必须对它们有一个完整且系统的认识与分析。
默认的 11 道 Filter
在 WebSecurityConfigurerAdapter 的 getHttp() 方法中,有这样一段代码:
if (!disableDefaults) {
// @formatter:off
http
.csrf().and()
.addFilter(new WebAsyncManagerIntegrationFilter())
.exceptionHandling().and()
.headers().and()
.sessionManagement().and()
.securityContext().and()
.requestCache().and()
.anonymous().and()
.servletApi().and()
.apply(new DefaultLoginPageConfigurer<HttpSecurity>()).and()
.logout();
// @formatter:on
ClassLoader classLoader = this.context.getClassLoader();
List<AbstractHttpConfigurer> defaultHttpConfigurers =
SpringFactoriesLoader.loadFactories(AbstractHttpConfigurer.class, classLoader);
for(AbstractHttpConfigurer configurer : defaultHttpConfigurers) {
http.apply(configurer);
}
}
这个地方便是配置默认 Filter 的地方,默认 Filter 的添加方式有两种:
- Spring security 自带的 11 道过滤器
- 用户自定义的过滤器(通过
SpringFactoriesLoader.loadFactories(AbstractHttpConfigurer.class, classLoader)获取)
在 Spring security 的设计中,每一道过滤器都有一个对应的配置器(configurer),http 后面每一个 and 就对应一个配置器的配置。从上面的代码中可以看到,总共有 11 道 Filter 的配置,它们分别为:
- csrf -> CsrfConfigurer ->
CsrfFilter WebAsyncManagerIntegrationFilter- exceptionHandling -> ExceptionHandlingConfigurer ->
ExceptionTranslationFilter - headers -> HeadersConfigurer ->
HeaderWriterFilter - sessionManagement -> SessionManagementConfigurer ->
SessionManagementFilter - securityContext -> SecurityContextConfigurer ->
SecurityContextPersistenceFilter - requestCache -> RequestCacheConfigurer ->
RequestCacheFilter - anonymous -> AnonymousConfigurer ->
AnonymousAuthenticationFilter - servletApi -> ServletApiConfigurer ->
SecurityContextHolderAwareRequestFilter - DefaultLoginPageConfigurer ->
DefaultLoginPageGeneratingFilter - logout -> LogoutConfigurer ->
LogoutFilter
从上面我们也可以看出,当 HttpSecurity 中没有提供我们需要的 Filter 的方法的时候,我们可以模仿 DefaultLoginPageConfigurer 或 WebAsyncManagerIntegrationFilter 的做法添加一个自定义的 Configurer 或者直接添加一个 Filter。通常,Configurer 存在的目的是为了方便用户自定义 Filter 内部的依赖,如果是用户自定义的 Filter 的话,没必要用一个 Configurer 去配置,直接添加一个 Filter 便可。
它们有什么用?
介绍完了上面的那么多的 Filter,它们都有什么作用呢?分别在 Spring Security 的认证与授权过程中扮演着什么样的角色?了解了这些知识点,对我们将 Spring Security 整合进自己的内部系统有着非常大的帮助,能够让我们更顺手的搭建与业务相关的安全服务。接下来的一系列的文章,便是对这些 Filter 进行介绍与内部实现的深究。