读懂 SSO

hong
1
2025-12-10

概述

当你在公司的内部系统上来回切换而不需要密码登录时,当你任意系统的登录态过期,跳转的授权页面都是统一的页面时,明明是不同的厂商给公司开发售卖的系统,但是却能够通过一个账号实现互联互通,你有没有想过,这背后,是什么驱动着这种链接?

答案就是本文所要说的 Single-Sign-On,单点登录,即我们常说的 SSO 登录。

传统认证体系

传统认证体系就是一个系统使用一套账号密码,在用户登录的时候通过对应系统的账号密码访问,但是当 有多个系统时,用户需要记住每一个系统的账密,存在心智负担,而用户为了记忆方便,选择共同使用一套账密,使得安全风险提升,当一个系统被破解后,就会引发多米诺骨牌效应,所有的系统都可以被快速破解。

此外,账密系统本身也很复杂,无论是初始开发还是后续升级,都需要投入大量的人力成本为每一个系统进行升级,再加上各系统之间的身份、角色、权限点的设置不同,难度也是不一样的。

所以为了解决这个困境,后来才提出了 SSO。

SSO 核心体系

什么是 SSO

单点登录(Single Sign-On,SSO)是为了解决跨系统身份认证的问题应运而生的,用户只需要一次认证,即可无缝访问所有相互信任的应用系统。

SSO 核心是:

  • 中央认证服务(Central Authentication Service,CAS):由可信的认证中心统一进行登录认证。
  • 票据机制:使用安全令牌(Ticket/Token)代替密码传递。
  • 会话代理:各个系统信任 CAS 颁发的凭证,而不需要重复的验证密码。

在了解 SSO 之前,你需要掌握一些关键术语:

术语职责示例
IdP (Identity Provider)身份提供者,负责认证用户Azure AD, Okta, Auth0
SP (Service Provider)服务提供者,依赖IdP的身份断言GitLab, Jira, 自研业务系统
SAML基于XML的认证协议,企业级应用主流企业内网系统集成
OAuth 2.0授权框架,常用于API访问控制第三方登录、开放平台
OIDC (OpenID Connect)基于OAuth 2.0的身份层,现代SSO首选云原生应用、移动端
TGT (Ticket Granting Ticket)建立全局会话的凭证,包含用户信息、票据生命周期等信息。
TGC (Ticket Granting Cookie)认证服务器认证成功后返回给浏览器的 cookie,与存储在认证服务器上的 TGT 相对应,TGC 和 TGT 类似于 cookie 和 session 的关系。
ST (Service Ticket)服务凭证,用于客户端验证用户身份

工作原理

一个经典的 CAS 流程图(以 OAuth 2.0 为例)以及关键步骤描述:

sequenceDiagram
    participant 用户浏览器
    participant SP(应用服务)
    participant IdP(认证中心)

    用户浏览器->>SP(应用服务): 1. 访问应用(无会话)
    SP(应用服务)->>用户浏览器: 2. 重定向到IdP授权端点
    用户浏览器->>IdP(认证中心): 3. 进入登录页,认证用户身份
    IdP(认证中心)->>用户浏览器: 4. 返回授权码,重定向回SP
    用户浏览器->>SP(应用服务): 5. 携带授权码请求回调
    SP(应用服务)->>IdP(认证中心): 6. 用授权码换取访问令牌
    IdP(认证中心)->>SP(应用服务): 7. 返回ID Token和Access Token
    SP(应用服务)->>SP(应用服务): 8. 验证令牌,创建局部会话
    SP(应用服务)->>用户浏览器: 9. 返回应用页面,正常访问
  1. 未登录态访问:用户访问SP,SP检查无有效会话,将用户重定向至IdP授权端点
  2. 授权请求:SP携带client_idredirect_uriresponse_type=codescope等参数请求授权
  3. 身份验证:IdP验证用户身份(若未登录则展示登录页),用户同意授权
  4. 授权码发放:IdP生成一次性授权码(Authorization Code),通过浏览器重定向回SP回调地址
  5. 换取令牌:SP使用授权码、客户端密钥向IdP令牌端点发起POST请求
  6. 令牌颁发:IdP验证授权码后,颁发ID Token(身份令牌)和Access Token(访问令牌)
  7. 会话建立:SP验证ID Token签名与声明,解析用户信息,创建局部会话(如设置Cookie)
  8. 后续访问:其他SP重复此流程,但因用户已在IdP建立会话,无需再次输入密码,实现SSO

上述这一系列优雅连贯的步骤背后还隐藏着一个核心的技术问题:HTTP 协议是无状态的,而 SSO 又是需要持续追踪用户认证状态的,那么我们要在哪里去保存这个状态实现持续的追踪呢?

SSO 对于状态的保存和共享,采取的解法就是中央会话存储安全令牌传递机制,通过三层架构实现认证流程的状态稳定:

  • 浏览器层:通过 Cookie 或者 Storage 存储客户端状态
  • 网络层:通过重定向、POST 请求传递一次性授权码
  • 服务器层:中央 IdP 维护全局会话,各个 SP 维护自身的局部会话

主流协议

业界实现的主流核心协议主要有以下几种:

  • CAS:Central Authentication Service,是一种基于票据的验证机制

    • 核心流程:

      1. 首次访问:用户首次访问 SP 时被重定向到 CAS 服务器登录,在登录成功后,CAS 生成 TGT(Ticket Granting Ticket) 存入 Cookie 中。
      2. 票据派发:CAS 根据 TGT 签发一次性的 ST(Service Ticket),通过回调地址返回给应用。而 SP 利用 ST 向 CAS 服务器验证身份,验证通过后,建立局部会话。
      3. 后续访问:用户访问其他应用时,浏览器将 TGT 携带在请求中,同步发送给 CAS 服务器,快速完成 ST 的换取,实现免登录。
    • 特点:流程清晰简洁,适合于内部系统

  • OAuth2.0/OIDC:基于授权码和 JWT 令牌的认证

    • 核心流程:

      1. 首次访问:用户首次访问 SP 时,重定向到授权服务器,登录成功后,此时返回授权码,而非令牌。授权码是一次性的。
      2. 令牌交换:应用 SP 用授权码向授权服务器换取 Access Token(访问令牌) 、 ID Token(身份令牌,JWT 格式)、Refresh Token(刷新令牌),这三者会打包返回。
      3. 身份验证:应用通过 ID Token 获取用户信息并建立会话,Access Token 用来调用资源服务器 API,Refresh Token 在后台静默续期,是一次性的,即,每次续期后失效,同时获取新的 Refresh Token。
    • 特点:基于 Token 机制,是无状态的,天然的支持跨域、移动端等场景。互联网应用首选方案。

  • SAML2.0:Security Assertion Markup Language 2.0,是基于 XML 断言的认证。

    • 核心流程:

      1. 首次访问:首次访问 SP 时,SP 生成 SAML 认证请求,该请求为 XML 格式,包含了签发者、回调地址等信息,通过浏览器重定向到 IdP。
      2. 身份验证:用户在 IdP 登录后,IdP 生成 SAML 响应,包含断言、数字签名、使用条件等信息,通过 POST 方式回调 SP。
      3. 断言认证:SP 响应 IdP 回调的信息后,提取用户信息并建立局部会话。
      4. 后续访问:用户访问其他 SP 时,浏览器会携带 IdP 持久化的 Cookie 信息(协议规范中没有明确这一要求,这是由 IdP 服务自行选择的),在 IdP 服务直接重新生成新的断言并完成登录。
    • 特点:基于 XML 数字签名,复杂度和安全性很高,但是不够轻量,一般用于金融、政务等场景。

    • SAML2.0 存在一个绑定机制,主要有三种实现方式:

      • HTTP-Redirect:SAMLRequest 通过 URL 参数 GET 传递,适合短请求
      • HTTP-POST:通过表单 POST 传递,无大小限制,安全性更高
      • Artifact:仅传递 artifact ID,SP 后台通过 SOAP 回调获取真实断言,最安全
sequenceDiagram
    participant 用户 as 用户浏览器
    participant SP as 应用服务(SP)
    participant IdP as 身份提供者(IdP)

    用户->>SP: 访问受保护资源
    SP->>用户: 生成 SAML Request 并重定向至 IdP
    用户->>IdP: GET 携带 SAML Request
    Note over IdP: 检查无全局会话
    IdP->>用户: 返回登录页面
    用户->>IdP: 提交用户名密码
    IdP->>IdP: 生成 SAML Response(含断言)
    IdP->>用户: POST SAML Response 至 SP ACS地址
    用户->>SP: 携带 SAML Response
    Note over SP: 验签、验证断言、创建局部会话
    SP->>用户: 设置 SP Cookie,返回资源
    Note over 用户,IdP: IdP 同时写入持久化 Cookie (TGC)
    
    用户->>SP: 访问另一SP应用
    SP->>用户: 生成 SAML Request 重定向至 IdP
    用户->>IdP: GET 携带 SAML Request
    Note over IdP: 存在全局会话(TGC),直接生成断言
    IdP->>用户: POST 新 SAML Response 至SP
    用户->>SP: 携带 SAML Response
    Note over SP: 验签后创建会话
    SP->>用户: 返回资源(无需再次登录)

实现方案

这里列举几个目前行业通用的 SSO 架构实现方案,以作为了解

这种方案是利用了浏览器的 Cookie 在同域下自动携带发送的特性,基于这个特性,我们将用户的登录态保存在服务端的 Session 中,Cookie 中保存的是 SessionID,在客户端与不同服务交互过程中,传递该 ID 给服务器用于判断。

典型应用:CAS 协议、同域 SSO 架构。

基于 Token 的 SSO

目前行业中使用最频繁的 SSO 方案,采用无状态的 JWT 令牌,由 IdP 签名提供给前端,在该令牌内同时包含了用户的身份和权限,存储在客户端的 storage 中,在后续前端和服务交互的过程中,前端每次发起请求时,都会自动的将 JWT 注入到请求头中(业务自行协商存放位置),在 SP 服务中,直接验证签名就可以确认身份,不需要实时的请求 IdP。

典型应用:OAuth 2.0,OIDC,跨域 SSO 架构。

安全防护

SSO 落地过程中,除了协议的实现外,还要面对着不少安全问题,因为 SSO 的设计上是“一次登录,全域通行”,所以如果 SSO 被攻破,就会引发全域风险,所以在 SSO 落地的时候,还需要建立多层的防护。

  1. 凭证泄露

    1. 场景:XSS 窃取 Cookie/localStorage 中的 JWT;中间人劫持未加密的 Cookie
    2. 应对:相关 SSO Cookie 禁止使用 JS 访问(Cookie 策略为 HttpOnly + Secure + SameSite);localStorage 中存放的 JWT 配合 CSP 策略防护;强制 HTTPS 协议,避免中间人劫持;缩短令牌有效期,避免泄露后损失扩大。
  2. CSRF 攻击

    1. 场景:恶意网站利用用户浏览器中的有效 Cookie 发起登录、登出请求
    2. 应对:关键请求增加 CSRF 令牌,确保请求来源合法;请求来源(Origin/Referer)增加白名单校验;禁止 Cookie 跨域携带。
  3. 凭证伪造与重放

    1. 场景:伪造 JWT Payload 越权;劫持 CAS 票据重复登录
    2. 应对:严格进行签名验证;凭证(ST、授权码)失效策略配置有效期、使用次数;账号异常检测

SSO 未来

SSO 诞生(以 SAML1.0 标准发布时间计算)至今,已有 24 个年头了,这么多年的演进,让 SSO 成为了企业和互联网平台的身份管理基础设施之一,而随着标准的不断丰富完善,以及身份管理场景的不断扩展,SSO 正朝着更加安全、便捷、智能的方向进行演进。

在安全性层面,无密码认证(FIDO2/WebAuthn)正在从根本上消除密码泄露风险,AI 驱动的自适应认证则能实时分析用户行为,动态调整认证强度,精准识别并阻断异常登录。同时,SSO 与零信任架构的深度融合,将身份验证从"一次性登录"扩展为"持续验证",每次资源访问均需重新评估身份与上下文,构建动态信任边界。

在便捷性与隐私层面,去中心化身份(SSI)赋予用户数据主权,身份凭证由用户自持而非集中托管,既提升隐私保护,又打破组织间身份孤岛。

综合看来,SSO 已经从原来简单的单点登录服务进化成为智能身份中枢,相信未来在无密码、AI 增强、去中心化这三大需求的驱动下,走向一次认证,全球通行的大一统时代。

参考文档

[1]: 理解 SAML2 协议 - SAML2 流程

动物装饰