跳到正文

SAML SSO 流程图:SP 发起与 IdP 发起的登录

SAML 2.0 单点登录如何运作:SP 发起和 IdP 发起的流程、SAML 响应包含什么、应用必须检查什么,以及容易出问题的地方。

· 创始人兼开发者

发布于

一张包含用户、浏览器、服务提供商和身份提供商的时序图。应用携带 AuthnRequest 重定向到 IdP;一个可选片段表示登录和 MFA;IdP 返回一个把 SAMLResponse POST 到 ACS URL 的表单;应用校验后设置 Cookie。

第一个签约的大客户会要求与他们的身份提供商做单点登录,而这往往意味着 SAML 2.0。这个标准诞生于 2005 年,通过浏览器重定向和表单提交来传递 XML,它的错误提示从含糊到干脆没有,不一而足。大多数 SAML 缺陷,包括严重的安全漏洞,都源于没有弄清楚哪条消息究竟发往哪里,以及服务提供商必须检查什么。

本文借助一张时序图,逐条消息地讲解 SP 发起的流程,然后介绍 IdP 发起的变体及其风险、SAML 响应的结构、应用的校验清单、元数据和证书轮换,以及 SAML 与 OpenID Connect 的对比。

三个参与方

参与方 SAML 术语 示例
用户的浏览器 用户代理 任意浏览器
你的应用 服务提供商(SP) 你的 SaaS 应用
客户的登录系统 身份提供商(IdP) Microsoft Entra ID、Okta、Google Workspace、AD FS

在常见的 Web Browser SSO 配置中,SP 和 IdP 从不直接通信。每条消息都以重定向或自动提交表单的形式经过浏览器。双方共享的是一次性交换的元数据配置:各自的 entity ID、IdP 的登录 URL、SP 的断言消费服务(ACS)URL,以及 IdP 的签名证书。

逐步拆解 SP 发起的流程

用户从你的应用开始:

  1. 用户在没有会话的情况下打开 https://app.example.com/dashboard。
  2. 应用创建一个 AuthnRequest,其中包含唯一 ID、自己的 entity ID 和 ACS URL,把这个 ID 存入待完成的登录状态,然后把浏览器重定向到 IdP。使用 HTTP-Redirect 绑定时,请求以 SAMLRequest 的形式(经 deflate 压缩并做 base64 编码)放在查询字符串里,旁边还有一个 RelayState 值,用来记住用户原本想去的地方。
  3. IdP 对用户进行认证:输入密码并完成 MFA,或者沿用已有的 IdP 会话,后一种情况下用户什么也看不到。
  4. IdP 返回一个 HTML 页面,其中的表单会把签名的 SAMLResponse 和同一个 RelayState POST 到你的 ACS URL。这就是 HTTP-POST 绑定,一小段脚本会自动提交表单。
  5. 应用校验响应,创建自己的会话 Cookie,并把用户重定向到 RelayState 中保存的页面。

从此以后,用户是谁由应用自己的会话决定。只有当这个会话过期时,SAML 才会再次参与。

绑定规范把 RelayState 限制在 80 字节以内,所以应把真实的返回 URL 存在服务端,只传一个短键。

SAML 响应包含什么

只保留应用会读取的部分,一个响应长这样:

<samlp:Response ID="_r81c" InResponseTo="_req42" Destination="https://app.example.com/saml/acs">
  <saml:Assertion ID="_a77e">
    <saml:Issuer>https://idp.customer.com/entity</saml:Issuer>
    <ds:Signature>…</ds:Signature>
    <saml:Subject>
      <saml:NameID>ana@customer.com</saml:NameID>
      <saml:SubjectConfirmationData InResponseTo="_req42"
        Recipient="https://app.example.com/saml/acs" NotOnOrAfter="2026-11-02T09:05:00Z"/>
    </saml:Subject>
    <saml:Conditions NotBefore="2026-11-02T08:59:30Z" NotOnOrAfter="2026-11-02T09:05:00Z">
      <saml:AudienceRestriction><saml:Audience>https://app.example.com</saml:Audience></saml:AudienceRestriction>
    </saml:Conditions>
    <saml:AttributeStatement>…email, name, groups…</saml:AttributeStatement>
  </saml:Assertion>
</samlp:Response>

断言是一份签名的声明:用户是谁(NameID),由谁声明(Issuer),面向谁(Audience),有效多久,以及是对哪个请求的应答(InResponseTo)。

校验清单

SAML 的安全成败取决于你的 ACS 端点。它必须:

  1. 用 IdP 元数据中的证书校验签名,绝不能用消息里自带的证书。
  2. 只读取签名覆盖的内容。 XML 签名包装攻击会插入第二个未签名的断言,指望代码校验一个元素却读取另一个。研究人员在 2012 年发现这一漏洞存在于 14 个主流 SAML 框架中的 11 个,而且它不断卷土重来:ruby-saml 在 2024 年修复了一个 CVSS 评分 10.0 的签名绕过漏洞(CVE-2024-45409),又在 2025 年修复了两个由解析器差异导致的绕过漏洞(CVE-2025-25291 和 CVE-2025-25292)。
  3. 检查 Issuer,与该客户的 IdP entity ID 比对。
  4. 检查 Audience,与你自己的 entity ID 比对。
  5. 检查 Destination 和 Recipient,与你的 ACS URL 比对。
  6. 检查 NotBefore 和 NotOnOrAfter,并为时钟偏差留出一两分钟的容差。
  7. 把 InResponseTo 与你为这个浏览器签发、且尚未使用过的 AuthnRequest ID 进行匹配。
  8. 拒绝重放,把断言 ID 记录到它们过期为止。
  9. 把 RelayState 视为不可信输入。 只重定向到相对路径或允许列表中的地址,否则就会出现开放重定向。

十年 SAML 漏洞史给出的教训是:使用持续维护的库,锁定版本,尽快打补丁,永远不要自己实现 XML 签名校验。

IdP 发起的 SSO 及其风险

在 IdP 发起的流程中,用户从 IdP 开始,通常是在 Okta 或 Microsoft My Apps 门户这样的面板上点击你应用的图标。IdP 会向你的 ACS URL POST 一个未经请求的响应。由于没有 AuthnRequest,也就没有可以匹配的 InResponseTo。

SP 发起 IdP 发起
起点 你的应用 IdP 的门户
AuthnRequest 有 无
InResponseTo 检查 有 无法进行
登录 CSRF 防护 内置 需要额外注意
深层链接 通过 RelayState 通常落在默认页面

没有 InResponseTo,攻击者一旦拿到一个有效响应,或者诱使受害者的浏览器提交一个响应,就能让受害者登录到攻击者的账户,或者在有效期内重放偷来的响应。如果客户需要面板图标,更安全的做法是让图标打开你应用的登录 URL,再由它发起正常的 SP 发起流程。如果必须接受未经请求的响应,就把有效期设短,强制断言 ID 只能使用一次,并且按客户逐个开放,而不是全局开放。

元数据、证书与多租户部署

每个客户的 IdP 都是一段独立的信任关系。按租户保存:IdP 的 entity ID、登录 URL、签名证书和属性映射。多租户 SaaS 架构图展示了这类按租户的配置通常放在哪里。

签名证书会过期,而过期或被更换的证书,是整个客户突然无法登录的最常见原因。在证书切换期间,每个 IdP 同时接受两张证书;如果 IdP 发布了元数据 URL,就定期读取;并在证书到期前数周发出告警。

SAML 负责认证,但不会帮你同步用户列表。首次登录时创建账户很容易,但有人离职时撤销访问权限需要用户预配,通常使用 SCIM 2.0(RFC 7644)。没有它,被停用的员工仍然保有应用已经签发的会话。

SAML 还是 OpenID Connect?

SAML 2.0 OpenID Connect
格式 带 XML 签名的 XML 断言 JSON,使用 JWT 格式的 ID 令牌
传输方式 浏览器重定向和表单提交 重定向加后端通道的令牌请求
移动应用和单页应用 用起来别扭 专为它们设计
典型用途 企业 SSO 登录 SaaS 应用 消费者登录、API、现代企业 SSO

新应用可以从 OpenID Connect 起步,但企业买家会一直要求 SAML,所以大多数 B2B 产品两者都支持。OAuth 2.0 流程图介绍了 OpenID Connect 所基于的协议。

SAML SSO 流程图

一张包含用户、浏览器、服务提供商和身份提供商的时序图。应用携带 AuthnRequest 重定向到 IdP;一个可选片段表示登录和 MFA;IdP 返回一个把 SAMLResponse POST 到 ACS URL 的表单;应用校验后设置 Cookie。

6 个组件 · 11 个连接

在 Archboard 中打开
图表内容
  • User
  • Browser
  • Service provider (your app)
  • Identity provider
  • no IdP session yet
  • 1. Open the app
  • 2. GET /dashboard (no session)
  • 3. 302 to IdP: SAMLRequest + RelayState
  • 4. GET /sso?SAMLRequest=…&RelayState=… (HTTP-Redirect)
  • 5. Login page
  • 6. Password + MFA
  • 7. HTML form: signed SAMLResponse + RelayState
  • 8. POST /saml/acs (HTTP-POST, auto-submit)
  • 9. 302 /dashboard + session cookie
  • 10. GET /dashboard (cookie)
  • 11. 200 OK
SP 发起的 SAML 单点登录。应用携带 AuthnRequest 把浏览器重定向到身份提供商,IdP 让用户登录后,把签名的响应 POST 到应用的 ACS URL,应用先校验响应,再创建自己的会话。

这张图的读法如下:

  • 四个参与者。 用户、浏览器、作为服务提供商的应用,以及身份提供商。时间自上而下流动。
  • 重定向经由浏览器,把 AuthnRequest 和 RelayState 从应用带到 IdP。
  • 可选片段是登录步骤。如果已有 IdP 会话,就会跳过这一步,用户只会看到一次快速的重定向。
  • 表单提交把签名的 SAMLResponse 送到 ACS URL。应用校验后设置自己的会话 Cookie。
  • Markdown 块列出了 ACS 端点必须完成的检查。

画出有助于排错的 SSO 流程图

  • 把浏览器画成独立的参与者。 SAML 是前端通道协议,隐藏浏览器就等于隐藏了消息可能被拦截或重放的位置。
  • 在每个箭头上注明绑定方式:重定向还是 POST,以及参数名。大多数配置错误都是 URL 或绑定方式写错了。
  • 在消息上标出 ID。 展示 InResponseTo 回显了请求 ID,就能说明为什么要检查它。
  • 把 IdP 发起的流程单独画出来,并注明风险,而不是作为主图的一个分支。

时序图示例更深入地介绍了参与者、片段和标签;零信任架构图则展示了身份提供商在更大的访问模型中的位置。

在 Archboard 中构建

  1. 使用 Google 或 GitHub 登录,并新建一张图。
  2. 添加一个时序节点包中的 参与者 表示用户,再添加三个 生命线 节点:Browser、Service provider 和 Identity provider。
  3. 自上而下把消息画成生命线之间的连线:最初的请求、带 SAMLRequest 和 RelayState 的重定向、发往 IdP 的请求、包含 SAMLResponse 的表单、向 ACS URL 的 POST,以及带会话 Cookie 的最终重定向。
  4. 在登录和 MFA 步骤外围添加一个时序节点包中的 组合片段,运算符设为 opt。
  5. 添加一个基础节点包中的 Markdown 块,写上校验清单。

这个示例共用 6 个图表节点,在 Free 套餐的限制之内。

常见问题

SP 发起和 IdP 发起的 SSO 有什么区别? SP 发起的登录从你的应用开始,由应用向 IdP 发送 AuthnRequest。IdP 发起的登录从 IdP 门户开始,由 IdP 向你的应用 POST 一个未经请求的响应。后者没有可以匹配的请求,因此对重放和登录 CSRF 的防护更弱。

什么是 ACS URL? 断言消费服务(ACS)URL 是你的应用中通过 HTTP POST 接收 SAML 响应的端点。它在 IdP 中配置,并且必须与每个响应中的 Destination 和 Recipient 值一致。

RelayState 有什么用? 它携带用户原本想访问的位置,让应用在登录后把用户带过去。它最多 80 字节,而且是不可信输入,所以应把它当作指向服务端状态的键,或者用允许列表进行校验。

SAML 过时了吗? 它比 OpenID Connect 更古老,也更难安全地实现,但仍是许多企业身份提供商和买家期望的标准。大多数 B2B 产品两者都支持。

用户离职后,SAML 会自动删除他们吗? 不会。SAML 只在登录时进行认证。撤销访问需要 SCIM 或其他用户预配集成,同时应用中的会话时长也要合理。

免费开始 — 1 个席位,无需信用卡。

相关文章

← 返回博客

一分钟打开画布

使用 Google 或 GitHub 登录。单席位免费,团队加入后再升级。