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