查找注册的Spring Security过滤器(Filter)

转自: https://www.baeldung.com/spring-security-registered-filters

1. 概述

Spring Security 是基于 链条的 servlet 过滤器的。每一个过滤器都有自己的责任并且依赖于添加和移除过滤器的配置。

在这个教程里,我们探讨一下查找注册的 Spring Security 过滤器的几种方式

2. Security 调试

首先,我们将启用Security调试,该调试将记录每个请求的详细安全性信息。

可以通过Spring Security debug 属性来开启:

1
@EnableWebSecurity(debug = true)

开启后,当请求服务的时候,所有请求信息日志会输出。

我们也可以把整个Security过滤器链看得到:

1
2
3
4
5
6
7
8
Security filter chain: [
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
LogoutFilter
UsernamePasswordAuthenticationFilter
// ...
]

3. 日志

接下来,我们通过开启FilterChainProxy的日志来查找 Security 过滤器。

可以通过把下述配置添加到 application.properties 来开启日志:

1
logging.level.org.springframework.security.web.FilterChainProxy=DEBUG

相关日志会是这么输出:

1
2
3
4
5
DEBUG o.s.security.web.FilterChainProxy - /foos/1 at position 1 of 12 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
DEBUG o.s.security.web.FilterChainProxy - /foos/1 at position 2 of 12 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
DEBUG o.s.security.web.FilterChainProxy - /foos/1 at position 3 of 12 in additional filter chain; firing Filter: 'HeaderWriterFilter'
DEBUG o.s.security.web.FilterChainProxy - /foos/1 at position 4 of 12 in additional filter chain; firing Filter: 'LogoutFilter'
DEBUG o.s.security.web.FilterChainProxy - /foos/1 at position 5 of 12 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'

4. 以编程的方式获取过滤器

接下来看一下怎么通过编程来获取被注册的Security过滤器。

我们通过 FilterChainProxy 获取 security 过滤器。

首先,注入 springSecurityFilterChain bean:

1
2
3
@Autowired
@Qualifier("springSecurityFilterChain")
private Filter springSecurityFilterChain;

这里我们用了命名为 springSecurityFilterChain@Qualifier,类型由FilterChainProxy替换成了Filter。这是因为 WebSecurityConfiguration里负责创建Spring Security 过滤器链的方法 springSecurityFilterChain() 的返回类型为 Filter 而不是 FilterChainProxy

接下来,我们把返回的对象类型转换成 FilterChainProxy 并且调用getFilterChains()方法:

1
2
3
4
5
6
7
public void getFilters() {
FilterChainProxy filterChainProxy = (FilterChainProxy) springSecurityFilterChain;
List<SecurityFilterChain> list = filterChainProxy.getFilterChains();
list.stream()
.flatMap(chain -> chain.getFilters().stream())
.forEach(filter -> System.out.println(filter.getClass()));
}

这是实例输出结果:

1
2
3
4
5
6
class org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter
class org.springframework.security.web.context.SecurityContextPersistenceFilter
class org.springframework.security.web.header.HeaderWriterFilter
class org.springframework.security.web.authentication.logout.LogoutFilter
class org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
...

请注意,从Spring Security 3.1开始,**FilterChainProxy是使用SecurityFilterChain列表配置的。**

但是,大多数应用程序仅需要一个。

5.重要的Spring Security滤器

最后,让我们看一些重要的安全过滤器:

  • UsernamePasswordAuthenticationFilter:处理身份验证,默认情况下响应 “/login” URL
  • AnonymousAuthenticationFilter:当SecurityContextHolder中没有身份验证对象时,它将创建一个匿名身份验证对象并将其放置在此处
  • FilterSecurityInterceptor:拒绝访问时引发异常
  • ExceptionTranslationFilter:捕获Spring Security异常

6. 总结

在这篇快速文章中,我们探讨了如何以编程方式和使用日志来查找已注册的Spring Security过滤器。

源码在 GitHub上: 地址