协议选型为什么重要

IAM 系统的核心任务是"把正确的身份信息,在正确的时机,以正确的方式,交给正确的应用"。而协议就是这条信息传递通道的语法和合同。

选错协议的代价不是"功能少了几个",而是:

问题类型典型后果实际案例
协议不匹配用 OAuth 做认证,结果拿到 Access Token 却不知道用户是谁早期很多开发者把 OAuth 2.0 当成"社交登录协议"用
过度设计在内部管理面板里用 SAML,每个 SP 都要交换 XML 元数据几十个内部工具维护 SAML metadata 的运维噩梦
协议混用OIDC + SAML 双栈但未统一会话管理,导致登出不同步用户在一个应用登出,另一个应用会话依然有效
安全盲区PKCE 缺失、redirect_uri 未校验、state 参数未使用OAuth 授权码拦截、CSRF、Mix-Up Attack

本章不重复 OAuth 2.0、OIDC、SAML 的协议细节——那些在 协议与标准部分有完整阐述。这里专注于决策:你面对一个具体场景时,该选哪个协议、为什么、不选其他协议的原因是什么。

五大协议的核心定位

在进入决策树之前,先理解每个协议在 IAM 体系中的核心角色——它们解决的是不同层面的问题

  graph TD
    subgraph "IAM 协议体系"
        AUTH_Z[授权<br/>OAuth 2.0] --> |构建于| AUTH_N[认证<br/>OpenID Connect]
        AUTH_N --> |替代/互补| SAML[SAML 2.0<br/>企业 SSO]
        DIR[LDAP<br/>目录查询] --> |用户源| AUTH_N
        DIR --> |用户源| SAML
        PROV[SCIM<br/>生命周期管理] --> |同步到| AUTH_N
        PROV --> |同步到| SAML
    end

    style AUTH_Z fill:#e1f5fe
    style AUTH_N fill:#c8e6c9
    style SAML fill:#fff9c4
    style DIR fill:#f3e5f5
    style PROV fill:#ffe0b2
协议核心问题在 IAM 中的位置数据格式典型端口
OAuth 2.0“我能做什么?(授权)”授权层——控制第三方应用对受保护资源的访问范围JSON通常 HTTPS
OpenID Connect (OIDC)“你是谁?(认证)”认证层——OAuth 2.0 + 身份层,标准化用户身份传递JSON (JWT)HTTPS
SAML 2.0“企业里的你是谁?(联邦认证)”身份联邦——跨组织/跨域传递用户身份断言XMLHTTPS / Redirect
LDAP“用户信息在哪?(目录查询)”用户存储——身份数据的查询、验证和修改协议ASN.1 / LDIF389 / 636
SCIM“用户怎么创建/更新/删除?(生命周期)”用户供应——自动化用户帐号的 CRUD 生命周期管理JSON (REST)HTTPS

一句话判断:需要授权第三方访问资源 → OAuth 2.0;需要证明"我是谁" → OIDC 或 SAML;需要连企业 AD → LDAP;需要自动创建/删除用户 → SCIM;需要跨公司 SSO → SAML 或 OIDC Federation。

IAM 协议选型决策树

下面这个决策树覆盖了企业 IAM 中最常见的 10 种场景。从你的需求出发,沿着分支走到叶子节点,就是推荐协议。

  graph TD
    START["我需要什么?"] --> Q1{"需要授权第三方<br/>访问我在另一个服务上的资源?"}
    Q1 -->|是| Q1A{"有用户在场吗?"}
    Q1A -->|是| REC_OAuth_Code["OAuth 2.0 Authorization Code + PKCE<br/>同时可选 OIDC 获取用户身份"]
    Q1A -->|否| Q1B{"是服务间通信?"}
    Q1B -->|是| REC_OAuth_CC["OAuth 2.0 Client Credentials Grant"]
    Q1B -->|否| Q1C{"是没有浏览器的设备?"}
    Q1C -->|是| REC_OAuth_DC["OAuth 2.0 Device Code Grant"]
    Q1C -->|否| Q1D{"用户输入密码可信?"}
    Q1D -->|是/仅内部| REC_OAuth_ROPC["OAuth 2.0 ROPC Grant<br/>⚠️ 不推荐,仅遗留兼容"]
    Q1D -->|否| REC_OAuth_Code

    Q1 -->|否| Q2{"需要跨组织 / 跨公司 SSO?"}
    Q2 -->|是| Q2A{"对方是否支持 OIDC?"}
    Q2A -->|是| REC_OIDC_FED["OIDC Federation<br/>或 OpenID Federation 1.0"]
    Q2A -->|否/传统企业| Q2B{"需要 SAML?"}
    Q2B -->|是| REC_SAML["SAML 2.0 SP-Initiated SSO"]
    Q2B -->|否| REC_OIDC["OpenID Connect"]
    Q2 -->|否| Q3{"应用类型?"}
    Q3 -->|"现代 SPA / 移动 App / API"| REC_OIDC_SPA["OIDC + PKCE<br/>使用 Authorization Code Flow"]
    Q3 -->|"传统 Web 应用<br/>/ .NET / Java EE"| Q3A{"技术栈偏好?"}
    Q3A -->|"已有 SAML 基础设施<br/>或使用 AD FS"| REC_SAML2["SAML 2.0"]
    Q3A -->|"现代化优先"| REC_OIDC_WEB["OIDC Authorization Code Flow"]
    Q3 -->|"需要查询/验证 AD/LDAP"| REC_LDAP["LDAP / LDAPS<br/>可选 Keycloak User Federation 封装"]
    Q3 -->|"需要自动化用户生命周期管理"| REC_SCIM["SCIM 2.0<br/>配合 IdP 的 SCIM 端点使用"]

    style REC_OAuth_Code fill:#c8e6c9
    style REC_OIDC fill:#c8e6c9
    style REC_OIDC_SPA fill:#c8e6c9
    style REC_OIDC_WEB fill:#c8e6c9
    style REC_OIDC_FED fill:#c8e6c9
    style REC_SAML fill:#fff9c4
    style REC_SAML2 fill:#fff9c4
    style REC_LDAP fill:#f3e5f5
    style REC_SCIM fill:#ffe0b2
    style REC_OAuth_CC fill:#e1f5fe
    style REC_OAuth_DC fill:#e1f5fe
    style REC_OAuth_ROPC fill:#ffcdd2

决策树使用说明

  1. 从顶部"我需要什么"开始,诚实回答自己的需求
  2. 一个项目可能涉及多个分支——例如一个 SaaS 产品可能同时需要 OAuth 2.0(第三方集成)、OIDC(用户登录)、SCIM(企业客户自动同步用户)
  3. 红色节点(ROPC Grant)表示有已知安全风险,仅限特定遗留场景

十个典型场景的协议选型

场景 1:SaaS 产品需要支持企业客户 SSO 登录

需求:让使用 Okta / Entra ID / Google Workspace 的企业客户,用他们自己的帐号登录你的 SaaS。

考量答案
推荐协议OIDC 为主,SAML 2.0 作为补充
为什么不是纯 SAML大多数现代 IdP 已支持 OIDC;OIDC 客户端实现简单、调试方便、JSON 可读性远好于 XML
为什么还要 SAML传统企业(金融/政府)和 Microsoft AD FS 生态仍然主要使用 SAML——如果不支持 SAML,你就放弃了一批大客户
实现策略OIDC 优先(80% 客户覆盖),SAML 作为"企业版"功能(剩余 20%)

实现时需要注意:Keycloak 可以同时作为 OIDC Provider 和 SAML IdP;Dex 只做 OIDC 到上游 IdP 的联邦代理,不原生支持 SAML。如果要用 SAML,Keycloak 比 Dex 更合适。

场景 2:内部工具统一登录(Grafana / Jenkins / Harbor / GitLab 等)

需求:公司内部 20-50 个 DevOps 工具需要单点登录。

考量答案
推荐协议OIDC(几乎所有现代 DevOps 工具都支持 OIDC)
配置方式oauth2-proxy 作为反向代理前置,或各工具原生 OIDC 集成
为什么不是 SAML配置成本高——每个工具的 SAML metadata 都要维护,内部环境没必要承受这个复杂度
特殊注意一些老工具(如 Jenkins 旧版)可能需要 SAML 插件,考虑升级或替换

场景 3:移动 App 需要登录

需求:原生 iOS/Android App 的用户登录。

考量答案
推荐协议OIDC Authorization Code + PKCE
为什么 PKCE 必须移动 App 无法安全保存 client_secret。PKCE 提供了等效的安全保障
推荐库AppAuth (iOS/Android),不要用 WebView 直接加载登录页
为什么不是 Implicit GrantOAuth 2.1 已废弃 Implicit Grant——它在移动端的攻击面(token 可能被拦截、无法验证 redirect_uri)已被 PKCE + Authorization Code 替代

场景 4:微服务间 API 调用需要授权

需求:Service A 调用 Service B 的 API,两个服务都是内部系统,没有用户参与。

考量答案
推荐协议OAuth 2.0 Client Credentials Grant
实现方式两个服务各有一个 client_id + client_secret,A 用它们向 IdP 换取 Access Token,然后带着 Token 调用 B
Token 传递如果走 API Gateway,Gateway 完成 Token 校验和转发;如果是直连,B 自己校验 Token(Introspection 或本地 JWT 验证)
为什么需要 OAuth 而不是简单的 API KeyClient Credentials 提供 token 过期、scope 限制、可撤销、审计日志——静态 API Key 做不到

场景 5:企业需要从 AD / LDAP 同步用户到 SaaS 平台

需求:企业有 AD 域控,需要在 SaaS 平台中自动创建/更新/禁用用户。

考量答案
推荐协议SCIM 2.0(用于用户生命周期管理)+ LDAP(用于数据读取和认证)
架构AD → LDAP 查询 → 同步工具/SCIM 网关 → SaaS 平台的 SCIM 端点
为什么不是直接暴露 LDAP暴露 LDAP 给互联网等于把目录服务暴露在攻击面下;SCIM 是 RESTful、有 Token 认证、支持过滤和分页
开源实现Keycloak 支持 LDAP User Federation(实时读取)、支持 SCIM 端点(通过扩展)

场景 6:电商网站需要"用微信/Google/Apple 登录"

需求:C 端用户不想注册新帐号,想用已有社交帐号登录。

考量答案
推荐协议OIDC(Google/Apple 已经支持 OIDC);微信使用的是变种 OAuth 2.0
IDP 端配置在 Keycloak Identity Provider 中添加 Google / Apple / 微信,它们会自动处理协议适配
帐号关联确保处理"同一个邮箱可能来自不同社交平台"的情况——Keycloak 的 Account Linking 可以解决

场景 7:两家公司合并后,员工需要互相访问对方的内部系统

需求:A 公司和 B 公司合并,A 的员工需要用 A 的帐号访问 B 的内部系统。

考量答案
推荐协议SAML 2.0(企业互信的传统方案)或 OIDC Federation(新方案)
为什么 SAML 是默认两家公司很可能已经各自有 IdP,SAML 是企业 IDP 互信的标准协议
实现架构IdP-to-IdP 联邦:A 的 IdP 配置 B 的 IdP 为 Trusted IdP,用户在 A 登录后访问 B 系统时由 B 的 IdP 信任 A 的断言
新趋势OpenID Federation 1.0 正在替代 SAML 的企业联邦场景,但生态成熟度还在爬坡

场景 8:IoT 设备需要上报数据到云平台

需求:一个没有浏览器、没有键盘的物联网设备,需要向云端 API 发送数据。

考量答案
推荐协议OAuth 2.0 Device Code Grant(首次配网时)或 Client Credentials(设备已有凭证)
Device Code 流程设备向 IdP 请求一个 device_code + user_code → 用户在手机上访问验证 URL 输入 user_code 确认 → 设备轮询获得 Token
为什么不是 Client Credentials 直接设备出厂时可能没有唯一凭证,Device Code 提供了"人在环"的授权确认
后续会话设备获取 Refresh Token 后可长期保持会话,不再需要用户交互

场景 9:需要在反向代理层做统一认证

需求:用 Nginx Ingress 或 Traefik 对所有后端服务做统一的身份校验,未登录用户不能访问任何内部页面。

考量答案
推荐协议OIDC(oauth2-proxy + ForwardAuth / auth-url)
Nginx Ingressoauth2-proxy 作为 auth-url 指向的验证服务,Nginx 根据验证结果放行或重定向
TraefikForwardAuth 中间件指向 oauth2-proxy 的 /oauth2/auth 端点
后端如何获取用户身份oauth2-proxy 会通过 X-Auth-Request-UserX-Auth-Request-EmailX-Auth-Request-Groups 等 HTTP Header 传递用户信息
详细配置参见 Keycloak + oauth2-proxy 集成指南Traefik ForwardAuth 配置

场景 10:需要从旧版 IAM 迁移到新版

需求:从自建 LDAP + 应用内认证迁移到 Keycloak 统一认证。

考量答案
涉及协议LDAP(读取旧数据)→ SCIM 或直接导入(迁移到新平台)→ OIDC(新应用接入)
迁移策略1) Keycloak 先通过 LDAP User Federation 连接旧 LDAP——用户认证无缝继续;2) 分批将应用从直连 LDAP 改为对接 Keycloak OIDC;3) 最后把 LDAP 中的用户数据导入 Keycloak 内置数据库,断开 LDAP 依赖
风险控制不要在迁移第一步就切 DNS 或改认证端点——先增强旧系统,再逐步替换
详细参考Keycloak LDAP/AD 联合配置指南

协议对比速查表

维度OAuth 2.0OIDCSAML 2.0LDAPSCIM 2.0
核心目的授权认证联邦认证目录查询用户生命周期
标准化组织IETFOpenID FoundationOASISIETFIETF
最新规范年份2012 (RFC 6749)2014 (Core 1.0)20052006 (RFC 4510)2015 (RFC 7643/7644)
传输格式JSON (parameter)JSON (JWT)XML (SAML Assertion)ASN.1 BERJSON (REST)
绑定/传输HTTP Redirect/Form POSTHTTP Redirect/Form POSTHTTP Redirect/POST/ArtifactTCP/TLSHTTP REST
实现复杂度中等中等(比 OAuth 多 ID Token 处理)高(XML 签名/加密复杂)低(简单查询)中等
调试难度低(HTTP 抓包)低(JWT 在线解码)高(Base64 XML 签名验证)
移动端支持✅ 原生支持✅ 原生支持⚠️ 需要额外处理❌ 不适用❌ 不适用
SPA 支持✅ (PKCE)✅ (PKCE)⚠️ 不推荐
跨组织 SSO❌ 不是认证协议✅ (OIDC Federation)✅ 原生支持
会话管理❌ 无定义✅ Session Management / Logout✅ SLO (单点登出)
用户信息标准化❌(各自实现)✅ UserInfo Endpoint✅ SAML Attributes✅ LDAP Schema✅ SCIM Schema
发现/配置✅ Discovery (.well-known)✅ Metadata XML❌(手动配置)✅ ServiceProviderConfig
角色/组映射✅ (Claims)✅ (Attributes)✅ (memberOf)✅ (Groups)
客户端注册动态或手动动态或手动手动(高成本)N/AN/A

选型避坑指南

坑 1:用 OAuth 2.0 做认证

OAuth 2.0 是授权协议,不是认证协议。获取到 Access Token 不意味着你知道用户是谁——Access Token 是为资源访问设计的,格式和内容没有标准化。

正确做法:如果需要认证,使用 OIDC(在 OAuth 2.0 基础上增加 ID Token)。如果只能拿到 OAuth 2.0 的 Access Token,至少用 Token Introspection 或 UserInfo Endpoint 来验证用户身份。

坑 2:在 Blazor/.NET/Java EE 之外用 SAML

SAML 的 XML 签名和加密对于现代 SPA 和移动 App 来说太重了。如果你在 React/Vue/Flutter 应用中接入 SAML,调试签名验证错误会让你怀疑人生。

正确做法:新应用默认用 OIDC;只有在对接已有 SAML IdP(如 AD FS、Shibboleth)时才用 SAML。如果后端是 .NET 或 Spring Security,这些框架对 SAML 的支持反而比 OIDC 更成熟——要具体情况具体分析。

坑 3:在公网暴露 LDAP

LDAP 的默认安全模型假设它在内网中运行。把 LDAP 暴露到互联网等于邀请攻击者暴力破解你的目录。

正确做法:用 SCIM 或 IdP 的 User Federation 功能封装 LDAP。如果需要外部访问,至少通过 VPN/Zero Trust 隧道,而不是直接开 389/636 端口。

坑 4:“五个协议全支持"的过度设计

一些团队会追求"完美”——同时支持 OIDC、SAML、LDAP、SCIM,再自己封装一套。结果每个协议的实现都在 80% 完成度时被放弃。

正确做法:MVP 阶段只支持 OIDC(覆盖 80% 场景),在客户明确需要 SAML 时再加。SCIM 在企业客户超过 10 个之前可以手动处理。LDAP 用 IdP 适配而不是自己裸写。

坑 5:忽略 Token 生命周期和刷新策略

选完协议只是第一步。Access Token 设多长?Refresh Token Rotation 要不要开?登出时前端 Token 清了但后端 Token 还有效怎么办?

正确做法:Access Token 设 5-15 分钟,Refresh Token 设 8-24 小时并开启 Rotation。登出时必须通知 IdP(OIDC RP-Initiated Logout 或 SAML SLO)。更多细节见 OAuth 2.0 Token 管理

IAM 协议选型 FAQ

Q1: OAuth 2.1 发布了,现有系统必须升级吗?

不需要立即升级,但应该逐步采纳 OAuth 2.1 的核心安全要求:强制 PKCE、禁止 Implicit Grant、要求精确的 redirect_uri 匹配、使用 iss 参数防止 Mix-Up Attack。这些改动可以在现有 OAuth 2.0 基础设施上实施。详情见 OAuth 2.1 变化详解

Q2: 中小企业只有 50 个员工,需要 IAM 协议吗?

需要,但不需要全量。 50 人的公司不需要 SCIM(手动建帐号够用),也不需要 SAML(没有跨组织 SSO 需求)。但必须要有 OIDC——至少用 Google Workspace 或 Microsoft 365 作为 IdP,让所有内部工具统一登录。本地帐号 + LDAP 的维护成本在小团队中往往被低估。

Q3: SAML 和 OIDC 能共存吗?会有什么问题?

能共存,但有代价。 Keycloak、Okta、Entra ID 都支持同时做 SAML IdP 和 OIDC Provider。主要问题是:

  1. 会话一致性——用户在 OIDC 端登出,SAML 端的会话可能还在(SLO 的实现一致性因 IdP 而异)
  2. 运维复杂度——两个协议的错误排查路径完全不同
  3. 团队培训成本——需要有人同时懂 JWT 和 XML 签名

如果能统一用 OIDC,就不要引入 SAML。只有当业务要求(如客户用的是 AD FS)无法满足时,再加 SAML 支持。

Q4: 用 Keycloak 的话,协议选择会不会更简单?

会简化很多。 Keycloak 在协议适配层做得很好——你在 Keycloak 里配置一个 Client(OIDC)或 Client(SAML),后端会自动处理协议细节。开发者只需要知道"我应该创建一个 OIDC Client 还是 SAML Client"。

Keycloak 的不足是它不原生支持 SCIM 服务端(需要通过扩展或外部 SCIM Bridge),也不直接暴露 LDAP 端口(通过 User Federation 反向读取 LDAP,而不是作为 LDAP Server)。

Q5: LDAP 是否应该被淘汰?什么时候可以不学它?

短期不会淘汰,但可以不被它束缚。 如果你:

  • 不在传统企业环境中工作(没有 AD)
  • 正在做一个新项目,没有历史包袱
  • 身份数据存储在数据库中而不是目录服务中

那你不需要 LDAP 的知识。但如果你的公司有超过 500 人的规模且用 Windows,你几乎一定会遇到 AD——这时理解 LDAP 的查询语法(特别是 memberOf 过滤器)是绕不过去的。

Q6: OAuth 设备授权流程(Device Code)为什么不能用于 SPA?

因为安全模型不同。 Device Code Grant 假设设备有输出能力(显示 user_code)且用户有第二个设备(手机/电脑)来完成认证。SPA 在同一浏览器中完成所有操作,应该用 Authorization Code + PKCE。把 Device Code 用于 SPA 反而引入了不必要的轮询开销和安全风险(user_code 可能被截获)。

与架构设计的衔接

协议选型和架构设计是 IAM 决策的两个维度:

  • 协议回答"用什么语言传递身份信息"——本章覆盖
  • 架构回答"身份数据放哪、谁做决策、如何扩展"——见 IAM 架构设计指南

二者需要同步决策。例如,选择了 SAML 意味着你的 IAM 需要支持 XML 签名验证和 Metadata 管理,这会增加运维复杂度从而影响架构的高可用设计。如果选择了 LDAP,你的架构中必须有一个组件承担 LDAP 查询的延迟风险。

建议先完成 协议选型(本章),再做 架构设计,最后确定 授权模型——这个顺序能减少 70% 的返工。

如果你的 IAM 平台需要同时支持多种协议(如 OIDC + SAML),选型完成后建议直接参考 IAM 多协议集成实战,其中包含跨协议会话统一、属性映射和常见排错。

小结

IAM 协议选型的核心原则只有一条:选最匹配问题域的协议,而不是最"先进"的协议。

  • OAuth 2.0 解决授权,OIDC 在其上解决认证
  • SAML 在企业联邦中仍有不可替代的地位,但对新应用它已不是最优选择
  • LDAP 是用户目录的"SQL"——底层基础设施,大多数开发者不需要直接和它打交道
  • SCIM 把"建帐号"从手动操作变成 API 调用,是企业 IAM 自动化的重要标志

如果你只记住一件事,记住这个:拿到一个需求,先问"这是授权还是认证?是内部还是跨组织?有用户在场还是服务间通信?"——三个问题能帮你过滤掉 80% 的错误选项。