1. 概述
Spring Security 基於 Servlet 過濾器鏈。每個過濾器都有特定的職責,並且根據配置,過濾器可以添加或刪除。在本教程中,我們將討論查找已註冊的 Spring Security 過濾器不同的方法
2. 安全調試
首先,我們將啓用安全調試,這將在每個請求上記錄詳細的安全信息。
我們可以使用 debug 屬性啓用安全調試:
@EnableWebSecurity(debug = true)
這樣,當我們向服務器發送請求時,所有請求信息都會被記錄。
我們還可以查看整個安全過濾器鏈:
安全過濾器鏈:[
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
LogoutFilter
UsernamePasswordAuthenticationFilter
// ...
]
3. 日誌記錄
接下來,我們將通過啓用 FilterChainProxy 的日誌記錄來查找我們的安全過濾器。
可以通過在 application.properties 中添加以下行來啓用日誌記錄:
logging.level.org.springframework.security.web.FilterChainProxy=DEBUG
以下是相關的日誌:
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. 編程方式獲取過濾器
現在,我們將看到如何編程方式獲取已註冊的安全過濾器。
我們將使用 FilterChainProxy 來獲取安全過濾器。
首先,讓我們自動注入 springSecurityFilterChain bean:
@Autowired
@Qualifier("springSecurityFilterChain")
private Filter springSecurityFilterChain;
這裏,我們使用了 @Qualifier 帶有名稱 springSecurityFilterChain 以及類型 Filter 而不是 FilterChainProxy。 這是因為 springSecurityFilterChain() 方法在 WebSecurityConfiguration, 它創建的 Spring Security 過濾器鏈,返回類型 Filter 並且不是 FilterChainProxy。
接下來,我們將此對象轉換為 FilterChainProxy 並調用 getFilterChains() 方法:
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()));
}
以下是示例輸出:
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 過濾器。