目录
- Spring Security 中的过滤器
- 多个过滤器链
- 多个过滤器链配置例子
- http.authorizeRequests() 开头是什么意思?
- 引用
Spring Security 中的过滤器
Spring Security 中认证、授权功能的实现机制是通过过滤器来实现的。Spring Security 中一共提供了 32 个过滤器,其中默认使用的有 15 个,看看过滤器的配置问题。
请求从客户端发起(例如浏览器),然后穿过层层 Filter,最终来到 Servlet 上,被 Servlet 所处理。
上图中的 Filter 我们可以称之为 Web Filter,Spring Security 中的 Filter 我们可以称之为 Security Filter,它们之间的关系如下图:
可以看到,Spring Security Filter 并不是直接嵌入到 Web Filter 中的,而是通过 FilterChainProxy 来统一管理 Spring Security Filter,FilterChainProxy 本身则通过 Spring 提供的 DelegatingFilterProxy 代理过滤器嵌入到 Web Filter 之中。
DelegatingFilterProxy 在 Spring 中手工整合 Spring Session、Shiro 等工具时都离不开它,现在用了 Spring Boot,很多事情 Spring Boot 帮我们做了,所以有时候会感觉 DelegatingFilterProxy 的存在感有所降低,实际上它一直都在。
多个过滤器链
上面介绍的是单个过滤器链,实际上,在 Spring Security 中,可能存在多个过滤器链。
当请求到达 FilterChainProxy 之后,FilterChainProxy 会根据请求的路径,将请求转发到不同的 Spring Security Filters 上面去,不同的 Spring Security Filters 对应了不同的过滤器,也就是不同的请求将经过不同的过滤器。
多个过滤器链配置例子
@Configuration
public class SecurityConfig {
@Bean
protected UserDetailsService userDetailsService() {
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withUsername("cf").password("{bcrypt}$2a$10$Sb1gAUH4wwazfNiqflKZve4Ubh.spJcxgHG8Cp29DeGya5zsHENqi").roles("admin", "aaa", "bbb").build());
manager.createUser(User.withUsername("chenfu").password("{noop}123").roles("admin").build());
manager.createUser(User.withUsername("臣服").password("{MD5}{Wucj/L8wMTMzFi3oBKWsETNeXbMFaHZW9vCK9mahMHc=}4d43db282b36d7f0421498fdc693f2a2").roles("user", "aaa", "bbb").build());
return manager;
}
@Configuration
@Order(1)
static class DefaultWebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/foo/**")
.authorizeRequests()
.anyRequest().hasRole("admin")
.and()
.csrf().disable();
}
}
@Configuration
@Order(2)
static class DefaultWebSecurityConfig2 extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/bar/**")
.authorizeRequests()
.anyRequest().hasRole("user")
.and()
.formLogin()
.permitAll()
.and()
.csrf().disable();
}
}
}
- 首先,SecurityConfig 不再需要继承自 WebSecurityConfigurerAdapter 了,只是作为一个普通的配置类,加上 @Configuration 注解即可。
- 提供 UserDetailsService 实例,相当于是我们的数据源。
- 创建静态内部类继承 WebSecurityConfigurerAdapter 类,同时用 @Configuration 注解标记静态内部类是一个配置类,配置类里边的代码就和之前的一样了,无需赘述。
- 每一个静态内部类相当于就是一个过滤器链的配置。
- 注意在静态内部类里边,我没有使用 http.authorizeRequests() 开始,http.authorizeRequests() 配置表示该过滤器链过滤的路径是 /。在静态内部类里边,我是用了 http.antMatcher("/bar/") 开启配置,表示将当前过滤器链的拦截范围限定在 /bar/**。
- 当存在多个过滤器链的时候,必然会有一个优先级的问题,所以每一个过滤器链的配置类上通过 @Order(2) 注解来标记优先级。
configure(HttpSecurity http) 方法就是在配置过滤器链!我们在该方法中的配置,都是在添加/移除/修改 Spring Security 默认提供的过滤器,所以该方法就是在配置 Spring Security 中的过滤器链。
http.authorizeRequests() 开头是什么意思?
首先,http.authorizeRequests() 配置并非总在第一行出现,如果只有一个过滤器链,他总是在第一行出现,表示该过滤器链的拦截规则是 /**(请求只有先被过滤器链拦截下来,接下来才会进入到不同的 Security Filters 中进行处理),如果存在多个过滤器链,就不一定了。
仅仅从字面意思来理解,authorizeRequests() 方法的返回值是 ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry,ExpressionUrlAuthorizationConfigurer 可以为多组不同的 RequestMatcher 配置不同的权限规则,就是大家看到的 .antMatchers(“/admin/**”).hasRole(“admin”).antMatchers(“/user/**”).hasRole(“user”)。
引用
- Spring Security 竟然可以同时存在多个过滤器链?