實現(xiàn)預認證
1. 前言
上一節(jié)我們討論了如何保存用戶登錄狀態(tài),本節(jié)我們討論另一個問題,如果無法在 Spring Security 中實現(xiàn)認證,又希望使用 Spring Security 做后續(xù)的安全處理該如何實現(xiàn)?
我們知道,Spring Security 既包含認證的標準,也包含鑒權的標準,而鑒權又是認證后續(xù)步驟。那如果我們希望 Spring Security 幫我們處理權限,而又希望跳過認證步驟(比如已在外部系統(tǒng)實現(xiàn)認證),這是該如何配置?我們就需要使用「預先認證」解決方案了。
本節(jié),我們重點討論如何用 Spring Security 實現(xiàn)預先認證效果。
2. 預先認證概述
預先認證的使用場景如:已使用x.509 認證、J2EE 容器等方式通過認證。預認證有兩個主要步驟:
- 識別發(fā)起請求的用戶身份;
- 為該用戶返回權限。
具體的運行機制與外部認證環(huán)境有關。當使用 x.509 證書認證時,用戶的識別信息從證書中獲取并添加在 Http 請求頭中。如果是 J2EE 容器認證,用戶的身份信息通過 Http 請求對象的 getUserPrincipal()
方法獲得。有時,外部認證系統(tǒng)可以提供用戶的身份信息、權限信息,但有時,權限信息要從其他數據源中獲取,例如通過 UserDetailsService
。
3. Spring Security 集成方法
3.1 框架層說明
由于大部分的預先認證模式比較一致,Spring Security 為此提供了一個框架,用來實現(xiàn)預先認證的身份提供器。預先認證模塊的實現(xiàn)類均在包 org.springframework.security.web.authentication.preauth
之下。
此處介紹幾個核心的成員對象。
3.1.1 AbstractPreAuthenticatedProcessingFilter
該類用來檢查當前安全上下文的有效性,如果內容為空,它會嘗試從 Http 請求中解析出用戶信息,并將其提交到認證管理器 AuthenticationManager
。使用該基類需要實現(xiàn)如下兩個方法:
- 獲取認證身份信息
protected abstract Object getPreAuthenticatedPrincipal(HttpServletRequest request);
- 獲取認證憑證
protected abstract Object getPreAuthenticatedCredentials(HttpServletRequest request);
通過對這兩個方法的調用,該過濾器將創(chuàng)建一個票據對象實例 PreAuthenticatedAuthenticationToken
,該實例包含用戶認證結果,并用于認證過程。但是此處的認證過程,僅僅是用來獲取權限,只是為了滿足標準 Spring Security 流程而實施的步驟。
和其他的安全過濾器類似,預先認證的過濾器包含一個 authenticationDetailsSource
屬性,用于保存預先認證流程中的相關數據。
3.1.2 J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource
如果前述過濾器配置了 authenticationDetailsSource
,其權限信息可以通過 isUserInRole(String role)
方法判斷,角色信息的配置通過 MappableAttributesRetriever
獲取,或者通過 <security-role>
標簽配置到 web.xml
文件中。
3.1.3 PreAuthenticatedAuthenticationProvider
預先認證身份提供者中的 UserDetails
對象與其他的身份提供者邏輯略有不同,主要體現(xiàn)在獲取 Authentication
認證信息時,僅需用戶名參數即可。
public interface AuthenticationUserDetailsService {
UserDetails loadUserDetails(Authentication token) throws UsernameNotFoundException;
}
3.1.4 Http403ForbiddenEntryPoint
對 AuthenticationEntryPoint 的配置用對未認證用戶來發(fā)起認證流程。在預先認證流程中,該配置不起作用,我們只需要配置 ExceptionTranslationFilter
用于處理安全過濾器無法獲得用戶信息的情形,通常在這種情況下,請求端將收到 403 錯誤。
3.2 具體實現(xiàn)說明
關于 x.509 認證的集成實現(xiàn),我們在后續(xù)文章中具體說明。
針對 J2EE 容器認證的集成實現(xiàn),需要指定其 authenticationDetailsSource
對象為 J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource
實例。
4. 小結
本節(jié)我們討論了如何在 Spring Security 中跳過認證過程,使用外部認證結果,本節(jié)主要知識點有:
- 預認證是指認證過程被安排在其他程序中完成的認證方式;
- 預認證是一類認證方式的統(tǒng)稱,最常見的預認證方式是 X.509 證書認證;
- Spring Security 集成預認證相當于讓認證過程什么都不執(zhí)行,只保留鑒別權限的功能。
下節(jié)我們討論如何使用 X.509 證書方式認證。