SAML2 認證集成
1. 前言
在前面的幾個小節里,我們討論了 Spring Security 如何集成 OAuth2.0 認證規范。本節我們討論另一種統一認證方案「SAML2.0」。
SAML 全稱 Security Assertion Markup Language,中文含義為安全斷言標記語言,目前該語言規范已升級到 2.0 版本。
和 OAuth2.0 相比,SAML2.0 的設計更為全面,涵蓋了聯邦認證、身份管理、單點登錄的總體標準(OAuth2.0 僅規定了開放授權規范,不處理身份驗證)。
SAML 2.0 常用于大型企業內部的統一身份認證服務,而在互聯網應用中很少出現。
本節重點討論 Spring Security 集成 SAML 2.0 認證的方法。
本小節實例開發環境:
本小節所使用的實例代碼是基于 Spring 官網中提供的最小化 HelloWorld 模板創建,請點此下載完整的 HelloWorld 模板壓縮包。
2. SAML 2.0 簡介
SAML2.0 基于 XML 標準,核心目標是在不同安全域(Security Domain)之間交換認證和授權數據。
SAML2.0 的主要組成有:
- 服務提供者(SP):類似于 OAuth2.0 中的資源服務,用來提供真正的商業服務;
- 身份鑒別者(IDP):提供用戶的身份鑒別服務,確保用戶的身份真實可信;
- 斷言消息(Assertions):用來描述認證的對象,比如用戶認證的時間、方式、基本及擴展信息(如:email、電話等);
- 協議(Protocol):是一系列的 Request 和 Response 對象的合集,代表著某個行為需要執行的操作序列;
- 綁定(Binding):代表了 SAML 信息通過何種通訊協議被傳輸,比如 HTTP、HTTP-POST、SOAP等;
- 元數據(MetaData):是 SAML 中的配置數據,比如 IP 地址、綁定類型等。
SAML 2.0 的認證過程如下:
3. SAML 2.0 認證集成
3.1 集成思路
SAML 2.0 認證登錄,可以理解為 SP 從 IDP 獲取 XML 格式斷言消息的過程。目前有兩種認證流程:
-
IDP 端發起方式。首先用戶直接在 IDP(例如 Okta 認證中心)登錄,然后選擇一個將要授權的 SP(例如 Web 應用),IDP 隨后發送斷言消息到 SP。
-
SP 發起方式。用戶首先訪問一個 SP,SP 向 IDP 發現認證請求,IDP 要求用戶登錄,如果登錄成功,IDP 將發送斷言消息到 SP。
當前 Spring Security 對 SAML 2.0 已支持的特性包括:
- 通過
entityId = {baseUrl}/saml2/service-provider-metadata/{registrationId}
形式聲明 SP; - 通過 HTTP POST \ Redirect 方法,從
{baseUrl}/login/saml2/sso/{registrationId}
接收 SAML 響應中的認證斷言; - 斷言簽名;
- 支持斷言內容加密;
- 支持對 Name ID 元素進行加密;
- 支持將認證斷言的屬性轉換為
Converter<Assertion, Collection<? extends GrantedAuthority>>
對象; - 允許使用
GrantedAuthoritiesMapper
管理權限白名單; - 使用
java.security.cert.X509Certificate
公鑰格式; - SP 通過
AuthNRequest
初始化認證流程。
3.2 代碼集成
- 開啟
saml2Login()
支持;
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.saml2Login() // 啟動 SAML2 認證支持
;
}
}
- 為 SAML 2.0 認證配置認證環境;
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.saml2Login()
.relyingPartyRegistrationRepository(...) // 配置認證環境
;
}
}
在 SAML 2.0 中,SP 和 IDP 都是作為可信成員,將其映射保存在 RelyingPartyRegistration
對象中,RelyingPartyRegistration
對象通過 HttpSecurity
實例中的 .saml2Login().relyingPartyRegistrationRepository()
方法實現其數值配置。
至此,最基礎的 SAML 2.0 的認證配置就已經完成了。
3.3 配置 RelyingPartyRegistration
SAML 2.0 認證的核心配置項都存在于 RelyingPartyRegistration
對象中。
3.3.1 URI 模板配置
在 SAML 2.0 協議中,每次請求都會產生一個 URI 參數,在 saml2Login
過程中,URI 可以包含以下變量信息:
- baseUrl
- registrationId
- baseScheme
- baseHost
- basePort
使用舉例如下:
{baseUrl}/login/saml2/sso/{registrationId}
3.3.2 可信成員配置
可信成員包含以下配置項:
registrationId
,必填項,是當前配置項的唯一標識。localEntityIdTemplate
,可選項,根據請求生成節點 ID 時所選用的模板。remoteIdpEntityId
,必填項,IDP 的唯一標識。assertionConsumerServiceUrlTemplate
,可選項,當由 SP 發起認證后,斷言成功的返回地址模板。idpWebSsoUrl
,必填項,IDP 做單點認證時的固定地址。credentials
,憑證列表,包含用于簽名、驗簽、加密、解密的證書。
3.3.3 從 SP 發起認證
從 SP 發起認證,最便捷的方法是訪問以下地址:
{baseUrl}/saml2/authenticate/{registrationId}
終端被訪問后,會通過調用 createAuthenticationRequest
方法生成 AuthNRequest
對象用于認證請求,如果需要對請求進行配置,可以增加通過如下方式:
public interface Saml2AuthenticationRequestFactory {
String createAuthenticationRequest(Saml2AuthenticationRequest request);
}
4. 小結
本節我們討論了 Spring Security 集成 SAML2.0 認證服務的方法,主要知識點有:
- Spring Security 在核心模塊中已包含了 saml2Login 啟動選項,可以用于構造 Saml 2.0 的 SP;
- Spring Security 目前版本對 Saml 2.0 支持并不完整,但可以滿足基本認證需求。
下節我們討論 Spring Security 集成 CAS 認證的方法。