1. 引言:为什么 SSO 是现代企业的"身份基石"?
在传统的企业 IT 环境中,用户每访问一个新系统(如 ERP、邮件、OA)都需要输入一次账号密码。这种"身份孤岛"现象带来了显著的现实痛点:
用户体验差:记忆数十个复杂密码导致"密码疲劳",频繁登录降低工作效率。
管理成本高:员工入职、离职或调岗时,管理员需在几十个系统中重复同步账号权限,极易出错。
安全风险剧增:为了好记,用户倾向于在所有系统使用弱密码;离职员工账号若未及时清理(孤儿账号),将成为黑客入侵的天然跳板。
单点登录(Single Sign-On, SSO) 的出现解决了上述问题。它允许用户只需在单一入口通过一次身份验证,即可获得访问所有相互信任系统的授权。作为 IAM(Identity and Access Management,身份认证与访问管理)的核心,SSO 不仅是效率工具,更是企业安全的第一道防线。
2. SSO 核心概念与基本原理
在深入协议前,我们必须统一语言。SSO 的本质是建立信任链条。
2.1 核心参与者
IdP (Identity Provider,身份提供方):认证中心,负责存储用户信息、执行认证(如校验密码、MFA)并签发凭证。
SP / RP (Service Provider / Relying Party,服务提供方/依赖方):最终用户要访问的应用系统,它信任 IdP 提供的认证结果。
Principal (主体):通常指试图访问资源的用户。
2.2 核心组件
Session (会话):用户与 IdP 之间建立的认证状态。
Token / Ticket (令牌/票据):一种证明身份的"数字通行证",由 IdP 签发,SP 校验。
Trust Domain (信任域):共享认证信息的系统集合。
2.3 基本逻辑流
用户访问 SP,SP 发现用户未登录。
SP 将用户重定向(Redirect)至 IdP。
用户在 IdP 完成登录,IdP 生成票据并通过浏览器传回 SP。
SP 拿着票据去 IdP 验证合法性(或通过公钥自验)。
验证通过,SP 建立本地会话。
3. 主流 SSO 协议深度对比
不同的业务场景决定了协议的选择。
维度
CAS (v2/v3)
SAML 2.0
OIDC (OAuth 2.0 + OpenID)
Kerberos
定位
经典 Web SSO 协议
企业级联合身份认证
现代互联网身份层
局域网/域控认证
票据形式
Ticket (ST/TGT)
XML Assertion
JSON Web Token (JWT)
二进制 Ticket
传送方式
浏览器重定向 + 后端校验
浏览器 POST (XML)
授权码流/隐式流
SPNEGO/GSSAPI
适用场景
传统高校、企业内部 Web
跨组织 B2B、SaaS 继承
移动端、SPA、API 保护
Windows 域环境
安全特性
依赖后端验证
XML 签名与加密
非对称加密签名、PKCE
对称加密、防重放
复杂度
中等
高(XML 处理复杂)
中(对开发者友好)
极高(需特定客户端支持)
移动端支持
差
较差
原生支持(极佳)
基本无
4. 经典协议流程深度解析
4.1 CAS (Central Authentication Service) 流程
CAS 是早期的行业标准,其核心是多级票据模型。
TGT (Ticket Granting Ticket):存储在 IdP Cookie 中,代表用户的 SSO 会话。
ST (Service Ticket):IdP 发给 SP 的一次性票据。
PGT (Proxy Granting Ticket):用于代理访问,解决 A 系统调用 B 系统时的身份透传。
登录时序:
用户访问 App -> 302 重定向到 CAS Server。
CAS 校验 TGT(若无则要求登录)。
CAS 产生 ST,重定向回 App:https://app.com?ticket=ST-xxxx。
后端校验 :App 后端携带 ST 请求 CAS serviceValidate 接口。
CAS 返回用户信息 XML,App 建立本地会话。
4.2 SAML 2.0 (Security Assertion Markup Language)
SAML 最大的特点是**"去中心化验证"**。SP 不需要像 CAS 那样再回连 IdP 校验,而是通过预先交换的公钥直接解析 XML 签名。
SP-Initiated (SP 发起) :用户先访问应用,应用生成 AuthnRequest 发给 IdP。
IdP-Initiated (IdP 发起) :用户先登录门户,点击应用图标,IdP 直接推给应用一个 SAMLResponse。
4.3 OIDC (OpenID Connect)
OIDC 是在 OAuth 2.0 授权协议之上增加的身份层。
核心流程(授权码流 + PKCE):
Code 交换 :App 请求 /authorize 获取 code。
PKCE 加固 :移动端使用 code_challenge 防止 code 被截获。
Token 兑换 :App 在后端用 code 换取 id_token (身份) 和 access_token (授权)。
go
复制代码
// OIDC Token 校验伪代码 (Golang)
func validateIDToken(rawIDToken string) (*claims, error) {
// 1. 验证签名 (RS256)
// 2. 验证 iss (发行人) 是否匹配
// 3. 验证 aud (客户端ID) 是否匹配
// 4. 验证 exp (过期时间)
return parseJWT(rawIDToken)
}
5. 安全风险与加固清单
SSO 是一把双刃剑:一旦 IdP 失陷,全线崩盘。
5.1 传输与会话安全 (Critical)
TLS & HSTS:强制全站 HTTPS。开启 HSTS (HTTP Strict Transport Security) 防止降级攻击。
Cookie 属性:
HttpOnly: 防止 XSS 窃取。
Secure: 仅 HTTPS 传输。
SameSite=Lax/Strict: 防范 CSRF 攻击。
Partitioned (CHIPS): 应对现代浏览器的第三方 Cookie 限制。
5.2 票据管理 (High)
短生命周期 :ST 或 Code 必须是一次性且有效期极短(通常 < 5分钟)。
Token Rotation (刷新令牌滚动):Refresh Token 使用一次后即废弃并下发新的,防止长期令牌泄露。
5.3 来源校验 (High)
重定向白名单 :这是最常见的漏洞(Open Redirect)。必须在 IdP 端严格校验 redirect_uri,禁止使用通配符。
Referer/Origin 校验:防止跨站请求伪造。
5.4 纵深防御 (Medium)
MFA (多因素认证):针对高敏感应用强制触发 TOTP 或 FIDO2 校验。
异常行为分析:同一账号在 1 分钟内异地登录(Impossible Travel)时强制阻断并告警。
6. 总结与 Checklist
SSO 的成功实施不仅在于选对协议,更在于后期的精细化运维。
运维 Checklist
元数据管理:SAML 证书是否即将在 30 天内过期?
日志审计 :是否记录了所有 login_success、login_failed 以及 token_exchange 日志?
SLO (Single Log-Out):用户注销 IdP 时,子系统是否能同步清理会话?(这是技术难点,建议配合后端短 Session 机制)。
监控告警:IdP 接口响应延迟是否超过 500ms?
灾备:IdP 挂了是否有"后门"账号或降级方案确保核心业务可用?