Spring Security 是 Spring 框架中提供的安全管理框架,它是基于 Servlet 过滤器实现的。
默认的过滤器链
Spring Security 在初始化时会自动生成一整套默认的过滤器链,这些过滤器链是按顺序有序地执行的。因为每个过滤器链都有特定的功能和处理逻辑,对于一个用户的请求,在整个过滤器链中会按照顺序经过每一个过滤器链的处理。最终,要么返回请求的处理结果,要么由后续过滤器链继续处理。
默认的过滤器链中包含以下过滤器:
WebAsyncManagerIntegrationFilter
- 异步响应的过滤器SecurityContextPersistenceFilter
- 安全上下文持久化过滤器HeaderWriterFilter
- 响应头写入过滤器CsrfFilter
- CSRF攻击过滤器LogoutFilter
- 登出过滤器UsernamePasswordAuthenticationFilter
- 用户名密码认证过滤器DefaultLoginPageGeneratingFilter
- 默认登录页面生成过滤器DefaultLogoutPageGeneratingFilter
- 默认登出页面生成过滤器BasicAuthenticationFilter
- 基础认证过滤器RequestCacheAwareFilter
- 缓存请求过滤器SecurityContextHolderAwareRequestFilter
- 认证信息和请求信息关联过滤器AnonymousAuthenticationFilter
- 匿名认证过滤器SessionManagementFilter
- 会话管理过滤器ExceptionTranslationFilter
- 异常处理过滤器FilterSecurityInterceptor
- 过滤安全拦截器
自定义Filter操作的步骤
如果默认的过滤器链中没有满足我们需求的过滤器,我们可以自定义一个过滤器,并且将这个过滤器添加到默认的过滤器链中。下面是自定义Filter的要点步骤:
- 继承
GenericFilterBean
类,实现业务逻辑,并重写doFilter
方法
public class MyFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
// do something...
// 调用过滤器链的下一个过滤器
filterChain.doFilter(servletRequest, servletResponse);
}
}
- 对过滤器进行配置,为过滤器添加 URL 匹配规则和执行顺序。将过滤器加入到 Spring Security 过滤器链中
@Configuration
public class MyWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// 添加自定义过滤器,并设置过滤器链中的执行顺序
http.addFilterBefore(new MyFilter(), UsernamePasswordAuthenticationFilter.class)
.authorizeRequests()
.anyRequest()
.permitAll();
}
}
示例
- 通过自定义过滤器在请求头中添加 Token
public class TokenFilter extends GenericFilterBean {
private static final String TOKEN_HEADER = "X-Token";
private static final String TOKEN_VALUE = "XXXXX";
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
response.addHeader(TOKEN_HEADER, TOKEN_VALUE);
filterChain.doFilter(request, response);
}
}
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterAfter(new TokenFilter(), BasicAuthenticationFilter.class);
http.authorizeRequests()
.anyRequest().authenticated()
.and().httpBasic();
}
}
- 通过自定义过滤器拦截特定的请求,实现限流功能
public class TokenBucketFilter extends GenericFilterBean {
private static final int TOKEN_BUCKET_SIZE = 100; // 令牌桶大小
private static final AtomicLong TOKEN_COUNT = new AtomicLong(0); // 当前令牌数
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
if (TOKEN_COUNT.get() >= TOKEN_BUCKET_SIZE) {
// 如果当前令牌数大于等于令牌桶大小,则返回 429 Too Many Requests 状态码
response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
} else {
// 如果当前令牌数小于令牌桶大小,将当前令牌数加 1
TOKEN_COUNT.incrementAndGet();
filterChain.doFilter(request, response);
}
}
}
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterAfter(new TokenBucketFilter(), BasicAuthenticationFilter.class);
http.authorizeRequests()
.anyRequest().authenticated()
.and().httpBasic();
}
}
以上示例分别实现了 Token 认证和限流两种基本的自定义过滤器功能,用到的类和方法都是 Spring Security 框架本身的 API,对于开发者而言非常友好和易于使用。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring Security之默认的过滤器链及自定义Filter操作 - Python技术站