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 认证的方法。