惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

宝玉的分享
宝玉的分享
NISL@THU
NISL@THU
E
Exploit-DB.com RSS Feed
L
LINUX DO - 热门话题
L
Lohrmann on Cybersecurity
K
Kaspersky official blog
Project Zero
Project Zero
Cisco Talos Blog
Cisco Talos Blog
T
The Exploit Database - CXSecurity.com
P
Palo Alto Networks Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
T
Threatpost
S
Schneier on Security
G
GRAHAM CLULEY
The Hacker News
The Hacker News
T
Threat Research - Cisco Blogs
Scott Helme
Scott Helme
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Privacy & Cybersecurity Law Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
Cyberwarzone
Cyberwarzone
C
CERT Recently Published Vulnerability Notes
T
Tor Project blog
AWS News Blog
AWS News Blog
Simon Willison's Weblog
Simon Willison's Weblog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
爱范儿
爱范儿
P
Privacy International News Feed
云风的 BLOG
云风的 BLOG
P
Proofpoint News Feed
S
Securelist
G
Google Developers Blog
The Last Watchdog
The Last Watchdog
Google Online Security Blog
Google Online Security Blog
美团技术团队
F
Fortinet All Blogs
小众软件
小众软件
Recorded Future
Recorded Future
V
Visual Studio Blog
B
Blog RSS Feed
H
Help Net Security
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Google DeepMind News
Google DeepMind News
Blog — PlanetScale
Blog — PlanetScale
博客园 - 聂微东
Stack Overflow Blog
Stack Overflow Blog
Martin Fowler
Martin Fowler
Latest news
Latest news
Spread Privacy
Spread Privacy
H
Heimdal Security Blog

土法炼钢兴趣小组的算法知识备份

国密算法与国密 TLS 系列索引 【系统架构设计】架构质量属性:不只是"高可用高性能" 【系统架构设计百科】告警策略:如何避免"狼来了" 【系统架构设计】CQRS:读写分离的架构哲学 【系统架构设计】空间架构:极端扩展场景的解法 【系统架构设计】微服务架构深度审视:优势、代价与适用边界 【系统架构设计】扩展性原理:水平、垂直与对角扩展 【系统架构设计】无状态设计:扩展的第一步也是最难的一步 【系统架构设计】缓存架构:从本地到分布式的多级缓存体系 【系统架构设计】管道与过滤器:Unix 哲学的架构表达 【系统架构设计】复杂性管理:架构的核心战场 【系统架构设计】消息队列架构:异步解耦的设计与陷阱 【系统架构设计】CDN 架构:全球加速的设计原理 【系统架构设计】连接池设计:被忽视的性能杀手 【系统架构设计】弹性设计模式:熔断器、舱壁与超时 【系统架构设计】高可用设计模式:冗余、故障转移与仲裁 【系统架构设计】容量规划:从拍脑袋到数据驱动 【系统架构设计】数据库扩展:分库分表的工程实践与替代方案 【系统架构设计】SLO 工程:可靠性的量化管理 【系统架构设计】性能建模:用数学思维分析系统瓶颈 【系统架构设计】混沌工程:主动验证系统的韧性 【系统架构设计】零拷贝与内存映射:数据搬运的极致优化 【系统架构设计】线程模型:从 thread-per-request 到协程 【系统架构设计】容灾架构:多活与灾备设计 【系统架构设计】数据库性能模式:索引、查询与连接管理 【系统架构设计】数据建模:从关系范式到文档模型的真实权衡 【系统架构设计】吞吐量优化:批处理、流水线与并发模型 【系统架构设计】流处理架构:从批处理到实时的范式迁移 【系统架构设计】搜索引擎架构:倒排索引之上的系统设计 【系统架构设计】时序数据架构:监控与 IoT 的存储设计 【系统架构设计】数据迁移与版本化:在线不停机的数据演进 【系统架构设计】数据湖与数据仓库:分析架构的演进路线 【系统架构设计】API 网关设计:入口层的职责边界 【系统架构设计】应用层数据一致性模式:在正确性与性能之间走钢丝 【系统架构设计】多模数据库选型:Polyglot Persistence 的工程实践 【系统架构设计】服务发现与注册:动态拓扑的基础设施 【系统架构设计】配置管理架构:从配置文件到配置中心 【系统架构设计】全链路压测:大规模系统的性能验证 【系统架构设计】幂等性设计:分布式环境下的安全重试 【系统架构设计】契约测试与 Schema 演进:服务间的信任协议 【系统架构设计】长连接与推送架构:WebSocket、SSE 与 MQTT 【系统架构设计】延迟分析:从 P50 到 P999 的全链路追踪 【系统架构设计百科】DDD 战术模式:聚合、实体与值对象 【系统架构设计百科】防腐层与开放主机服务:系统集成的 DDD 方案 【系统架构设计百科】领域事件与事件风暴:从业务到架构的桥梁 【系统架构设计百科】CQRS + Event Sourcing 完整实战:从领域建模到部署 【系统架构设计百科】DDD 与微服务:用领域模型划分服务边界 【系统架构设计】DDD 战略设计:限界上下文与上下文映射 【系统架构设计百科】认证架构:从 Session 到 JWT 到 OIDC 【系统架构设计】API 设计哲学:REST vs GraphQL vs gRPC 的真实权衡 排序算法专题:从 TimSort 到并行排序 【密码学百科】国密算法体系:SM2/SM3/SM4/SM9 全景解读 【密码学百科】承诺方案:Pedersen 承诺、向量承诺与多项式承诺 【密码学百科】不经意传输与隐私信息检索:OT、OT 扩展与 PIR 【密码学百科】门限密码学:门限签名、门限解密与分布式密钥生成 完美哈希:从理论到 gperf 实践 【密码学百科】安全多方计算:从 Yao 的混淆电路到实用 MPC 【密码学百科】同态加密:从 Paillier 到全同态加密(FHE) 【密码学百科】零知识证明系统:zk-SNARKs、zk-STARKs 与 Bulletproofs 【密码学百科】概率论与密码分析:生日攻击、差分分析与线性分析 【密码学百科】计算复杂性与归约:密码安全性证明的基石 【密码学百科】秘密共享:Shamir 方案、VSS 与安全多方计算入口 【密码学百科】椭圆曲线代数:Weierstrass 方程、点群运算与曲线选择 【密码学百科】离散对数与配对密码学:从 DLP 到 BLS 签名 【密码学百科】格密码数学基础:SVP、LWE 与格基约化 【密码学百科】抽象代数:群、环、域的密码学视角 【密码学百科】有限域算术:GF(2^n) 运算与在 AES/ECC 中的应用 【密码学百科】数论进阶:二次剩余、椭圆曲线上的 Weil 配对 【密码学百科】密码学简史:从凯撒密码到量子时代 【密码学百科】威胁模型与安全目标:CIA 三要素之外 【密码学百科】Kerckhoffs 原则与现代密码设计哲学 【密码学百科】随机性:密码学的基石 【密码学百科】信息论入门:熵、完美保密与 Shannon 定理 【密码学百科】分组密码原理:Feistel 网络与 SPN 结构 【密码学百科】AES 逐步拆解:SubBytes 到 MixColumns 的数学 【密码学百科】分组密码工作模式全览:ECB/CBC/CTR/OFB/CFB 【密码学百科】流密码:RC4 的兴衰与 ChaCha20 的崛起 【密码学百科】密码学哈希函数:MD5→SHA-2→SHA-3 的进化之路 【密码学百科】MAC 与 HMAC:消息认证的正确姿势 【密码学百科】认证加密(AEAD):GCM、ChaCha20-Poly1305 与 OCB 【密码学百科】密钥派生函数:HKDF、PBKDF2、Argon2 与密码存储 【密码学百科】公钥密码的数论基础:模运算、群、原根 【密码学百科】RSA 从原理到攻击:教科书 RSA 为什么不安全 【密码学百科】Diffie-Hellman 密钥交换与离散对数问题 【密码学百科】椭圆曲线密码学(ECC):从几何直觉到点群运算 【密码学百科】数字签名:ECDSA、EdDSA 与 Schnorr 签名 【密码学百科】现代密钥交换:X25519、ECDHE 与前向保密 【密码学百科】混合加密与 KEM/DEM 范式:ECIES 与 HPKE 【密码学百科】填充方案:PKCS#1 v1.5、OAEP 与 PSS 【密码学百科】TLS 协议全解析:从握手到 0-RTT 【密码学百科】PKI 与数字证书:信任链的构建与崩塌 【密码学百科】密码认证协议:从 SRP 到 OPAQUE 【密码学百科】零知识证明入门:如何证明你知道而不泄露 【密码学百科】安全信道构造:Noise 协议框架与 Signal 协议 【密码学百科】密钥管理工程:HSM、KMS 与密钥生命周期 【密码学百科】侧信道攻击:从时序攻击到功耗分析 【密码学百科】密码学实现陷阱:三层漏洞分类、审计工具链与系统性预防 密码敏捷性:如何设计可升级的密码系统 【密码学百科】OpenSSL/BoringSSL 架构剖析:ENGINE、Provider 与 FIPS 模块 排序基准测试:用数据说话
【身份与访问控制工程】SAML 还值得学吗:企业遗留 SSO 的现实世界
Liao Tonglang · 2026-04-21 · via 土法炼钢兴趣小组的算法知识备份

一个常见的质疑是:“OIDC 已经赢了,为什么还要学 SAML?”

答案在实际的销售合同中。当你做 B2B SaaS,第一个要求”接 SSO”的企业客户——通常是 500 人以上的中大型公司——发给你的可能不是 OIDC metadata URL,而是一个 XML 格式的 Federation Metadata 文件。因为他们的 IT 部门在过去十年间围绕 Microsoft ADFS、PingFederate 或 Shibboleth 搭建了整个企业 SSO 体系,而这些东西的通用语言是 SAML 2.0。

截至 2026 年,SAML 在企业 SSO 领域的存量仍然庞大。Microsoft Entra ID(原 Azure AD)、Okta、OneLogin、PingFederate 都同时支持 SAML 和 OIDC,但大量存量企业客户使用的就是 SAML 集成。你可能不需要在新建系统时选择 SAML,但你需要能读懂它、调试它、在企业客户说”我们只支持 SAML”时接住它。

一、SAML 2.0 的核心概念

SAML 2.0(Security Assertion Markup Language,OASIS Standard, 2005)的核心思想比 OAuth/OIDC 更简单:身份提供方(IdP,Identity Provider)签发一个 XML 格式的断言(Assertion),服务提供方(SP,Service Provider)验签后信任其中的身份信息。

关键角色:

角色 OIDC 对应 职责
IdP(Identity Provider) OP(OpenID Provider) 认证用户,签发 SAML Assertion
SP(Service Provider) RP(Relying Party) 接收 Assertion,建立本地会话
Principal(主体) User 被认证的用户
Assertion ID Token 包含用户身份信息的安全声明

SAML 和 OIDC 在概念层是同构的——都解决”IdP 告诉 SP 用户是谁”——但协议细节天差地别。

2.1 SP-Initiated SSO(服务提供方发起)

用户访问 SP 受保护资源 → SP 将用户重定向到 IdP → IdP 认证用户 → IdP 将用户重定向回 SP,携带 SAML Response → SP 验证签名和断言,建立会话。

sequenceDiagram
    participant User as 用户
    participant SP as 应用 (SP)
    participant IdP as 企业 IdP

    User->>SP: 1. 访问受保护资源
    SP->>SP: 2. 生成 SAML AuthnRequest
    SP->>User: 3. 302 到 IdP SSO URL + AuthnRequest
    Note over User,IdP: SAML AuthnRequest 经过浏览器

    User->>IdP: 4. POST SAML AuthnRequest
    IdP->>User: 5. 认证(可能已有会话,跳过)
    IdP->>IdP: 6. 生成 SAML Response (含 Assertion)
    IdP->>User: 7. 自动提交表单到 SP ACS URL
    Note over User,SP: SAML Response 经过浏览器 POST

    User->>SP: 8. POST SAML Response 到 SP ACS
    SP->>SP: 9. 验证签名、断言条件、受众
    SP->>User: 10. 建立本地会话, 302 到目标页面

SAML AuthnRequest 是一个经过 Base64 编码的 XML,作为 URL 参数传输。典型格式:

<samlp:AuthnRequest
  xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
  ID="_abc123"
  Version="2.0"
  IssueInstant="2026-06-14T10:00:00Z"
  Destination="https://idp.example.com/sso"
  AssertionConsumerServiceURL="https://sp.example.com/acs"
  ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST">
  <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
    https://sp.example.com
  </saml:Issuer>
</samlp:AuthnRequest>

2.2 IdP-Initiated SSO(身份提供方发起)

用户已登录 IdP → 在 IdP 门户点击 SP 的图标 → IdP 生成 SAML Response → POST 到 SP ACS URL → SP 建立会话。

IdP-Initiated SSO 绕过了 AuthnRequest 的步骤——SP 是被动接收方。这意味着 SP 无法传递 RelayState(目标页面),IdP 也不会知道用户在 SP 中想去哪里。而且,IdP-Initiated SSO 缺少 AuthnRequest 的 IDIssueInstant,SP 无法验证这个 Response 是对一个有效请求的响应——这是潜在的 Replay 风险。

工程陷阱 1:IdP-Initiated SSO 不在 SP-Initiated 的 CSRF 保护范围之内。如果 SP 没有额外的防重放措施(如对 Assertion ID 做去重),攻击者可以重放一个截获的 SAML Response 来登录。商用 IdP 通常给 Assertion 设置很短的 NotOnOrAfter 有效期(一般 5 分钟以内),这提供了有限的防护窗口。

三、SAML Assertion 的关键字段

一个 SAML Assertion 包含以下核心信息块:

<saml:Assertion ID="_def456" IssueInstant="2026-06-14T10:00:30Z" Version="2.0">
  <saml:Issuer>https://idp.example.com</saml:Issuer>

  <!-- 签名 -->
  <ds:Signature>...</ds:Signature>

  <!-- 条件:有效期 + 受众限制 -->
  <saml:Conditions NotBefore="2026-06-14T10:00:00Z" NotOnOrAfter="2026-06-14T10:05:00Z">
    <saml:AudienceRestriction>
      <saml:Audience>https://sp.example.com</saml:Audience>
    </saml:AudienceRestriction>
  </saml:Conditions>

  <!-- 认证声明:IdP 怎么认证用户的 -->
  <saml:AuthnStatement AuthnInstant="2026-06-14T10:00:00Z">
    <saml:AuthnContext>
      <saml:AuthnContextClassRef>
        urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
      </saml:AuthnContextClassRef>
    </saml:AuthnContext>
  </saml:AuthnStatement>

  <!-- 属性声明:用户信息 -->
  <saml:AttributeStatement>
    <saml:Attribute Name="urn:oid:1.2.840.113549.1.9.1.1">
      <saml:AttributeValue>user@company.com</saml:AttributeValue>
    </saml:Attribute>
    <!-- 更多属性... -->
  </saml:AttributeStatement>

  <!-- 主体 -->
  <saml:Subject>
    <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">
      user@company.com
    </saml:NameID>
    <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
      <saml:SubjectConfirmationData
        NotOnOrAfter="2026-06-14T10:05:00Z"
        Recipient="https://sp.example.com/acs"
        InResponseTo="_abc123"/>
    </saml:SubjectConfirmation>
  </saml:Subject>
</saml:Assertion>

SP 的验证步骤:

  1. 验证签名:用 IdP 的公钥验证 XML Signature(<ds:Signature>)或整个 SAML Response 的签名。
  2. 验证时间条件NotBefore ≤ 当前时间 < NotOnOrAfter
  3. 验证受众Audience 必须等于 SP 自己的 entity ID(即 issuer)。
  4. 验证 SubjectConfirmationDataRecipient 必须等于 ACS URL,InResponseTo(如果存在)必须等于 SP 发出的 AuthnRequest 中的 ID
  5. 验证 NameID:确认用户标识符的格式和值在预期范围之内。
  6. 去重:记录 Assertion ID(_def456),拒绝重复使用。

四、NameID 的选择:比你想象的麻烦

SAML 的 NameID 是用户在 SP 中的标识符。和 OIDC 的 sub 不一样——sub 在同一个 IdP 下全局唯一,NameID 可以有不同的 Format,而且格式决定了语义:

Format 示例值 语义
urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress user@company.com 邮箱地址
urn:oasis:names:tc:SAML:2.0:nameid-format:persistent JAv2pHy8rNkMp 不透明持久标识——同一个用户每次登录拿到的 NameID 相同,但不同 SP 间不同(pairwise pseudonymous)
urn:oasis:names:tc:SAML:2.0:nameid-format:transient t+N3cVxKzLpXq 临时标识——每次登录都不同(用于隐私场景)
urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified 任意字符串 由 IdP 和 SP 协商决定

最麻烦的场景:两个 SP(SP-A 和 SP-B)需要关联同一个用户。如果 IdP 对两个 SP 用的都是 persistent,两边的 NameID 值会不同——无法通过 NameID 直接关联。解决办法有两种:

  1. 使用 emailAddress:但依赖于邮箱格式的稳定性和唯一性(改名、离职后重用都会出问题)。
  2. 在 Attributes 中传递通用标识:如 SAML Attribute urn:oid:0.9.2342.19200300.100.1.1(uid),让多个 SP 用同一个属性做关联。

工程陷阱 2:企业客户的 IdP 管理员可以配置 NameID 的 Format 和来源。你会发现客户的 IdP 发来的 NameID 可能不是邮箱,甚至可能是一串你不认识的数字(如 AD 的 objectGUID 的 Base64 编码)。确认”SP 用什么来唯一标识用户”是 SAML 集成的第一件事。

SAML Metadata 是一个 XML 文件,描述了 IdP 或 SP 的技术配置——包括 Entity ID、证书公钥、端点 URL、支持的 NameID Format、断言的签名和加密选项。它的作用类似于 OIDC 的 Discovery 文档,但 XML 比 JSON 难读得多。

企业客户的 IT 部门通常会把 IdP Metadata 的 XML 文件(或 URL)发给你,你把它导入你的 SP 配置后,SSO 集成就完成了配置侧的大部分工作。反过来,你也可能需要提供你 SP 的 Metadata 给对方——尤其是如果你的 SP 需要签名或加密时(对方需要知道你的公钥)。

Metadata 中最重要的片段:

<md:IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
  <md:KeyDescriptor use="signing">
    <ds:KeyInfo>
      <ds:X509Data>
        <ds:X509Certificate>MIIE...</ds:X509Certificate>
      </ds:X509Data>
    </ds:KeyInfo>
  </md:KeyDescriptor>
  <md:SingleSignOnService
    Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
    Location="https://idp.example.com/sso"/>
  <md:SingleSignOnService
    Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
    Location="https://idp.example.com/sso/post"/>
  <md:NameIDFormat>
    urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
  </md:NameIDFormat>
</md:IDPSSODescriptor>

工程陷阱 3:Metadata 中的 X.509 证书用于验证签名,不是用于 TLS/HTTPS(那是 Web 服务器证书的事)。证书会过期——到期前 IdP 管理员会更新 Metadata。SP 必须支持 Metadata 的自动刷新或至少提供证书过期的监控和告警。证书突然过期导致所有 SAML SSO 登录失败是一个经典的 P0 事故。

六、SAML vs OIDC:什么时候用哪个

维度 SAML 2.0 OIDC
数据格式 XML JSON
传输方式 HTTP-Redirect / HTTP-POST with HTML form HTTP Redirect + POST (JSON)
移动端友好 差(需要浏览器重定向和表单 POST) 好(原生 App 可直接处理)
会话登出 SAML Single Logout(复杂,兼容性差) RP-Initiated Logout(简单,广泛支持)
企业存量 巨大(ADFS、Shibboleth、老 Okta) 快速增长(新系统默认选择)
部署复杂度 高(Metadata 交换、证书管理) 中低(Discovery URL 即开即用)
何时用 客户已有 SAML IdP,不愿意改;需要 SAML 特定功能(如 Single Logout) 新系统默认选择;移动端;B2C

工程判断:对于 B2B SaaS,你需要同时支持 SAML 和 OIDC。90% 的新客户会选 OIDC,但第一个大客户来的时候很可能要 SAML。

七、小结

SAML 今天不值得作为新系统的首选方案,但值得作为企业 SSO 的必接协议。核心工程要点:

  1. 实现 SP-Initiated SSO 和 IdP-Initiated SSO(两者都要)。
  2. 做好 Metadata 管理与证书过期监控。
  3. 与客户对齐 NameID 的 Format 和来源。
  4. 如果可能,在 SAML 上层抽象出通用的 SSO 集成层——OIDC 和 SAML 在你的系统内部应映射到相同的用户标识和会话管理流程。

上一篇OAuth 2.1 与 PKCE:现代授权主路径 下一篇SCIM 与账号生命周期:开通、变更、离职自动化

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-06-13 · architecture / security

【身份与访问控制工程】IAM 全景:为什么这是高价值赛道

从 2020 年 SolarWinds 到 2024 年 Okta 支持系统泄露,身份基础设施的安全失败反复证明一件事:IAM 不是 IT 支撑系统,而是安全架构的承重墙。本文建立现代 IAM 的全景地图——从认证协议、令牌体系、权限模型到身份治理与平台选型,给出 5 个贯穿全系列的核心问题。

2026-06-13 · architecture / security

【身份与访问控制工程】企业单点登录:OIDC 与现代 SSO

OIDC 是当下企业 SSO 的事实标准,但大多数实现只用了它 20% 的规范。本文从 OIDC 核心规范出发,拆解 Authorization Code Flow + PKCE 的完整交互、ID Token 的验证规则、Discovery 与 Dynamic Registration 的互操作性机制,以及 RP-Initiated Logout 和 Session Management 的工程实现细节。

2026-06-20 · architecture / security

【身份与访问控制工程】Keycloak 工程拆解:Realm、Client、Flow 与扩展机制

Keycloak 是 CNCF Incubating 项目中最成熟的 IAM 平台,也是自建身份系统的首选开源方案。但它不是'下个 JAR 跑起来就行'的简单软件——Realm 的隔离模型、Authentication Flow 的执行引擎、Client Scope 和 Protocol Mapper 的职责分离、自定义 SPI 扩展点——理解这些内部架构才能做好生产部署。本文从 Keycloak 的核心概念模型出发,拆解其内部执行路径和扩展机制。

2026-04-21 · architecture / security

身份与访问控制工程

从 OIDC、OAuth 2.1、SAML、SCIM 到多租户权限、CIAM、PAM 与身份平台选型——系统拆解现代身份与访问控制的协议、架构与工程实践。