企业里做单点登录(SSO),技术选型环节最容易卡住:SAML 2.0、OAuth 2.0、OIDC、CAS、JWT------名字都听过,但到底该用哪个?用友 ERP 怎么接?泛微 OA 怎么接?那个厂商已经不存在的老系统怎么接?
这篇文章把协议选型讲清楚,再按"能改造 / 半改造 / 不能改造"三类系统给出具体接入方案。内容基于安当 ASP 统一身份认证平台的实施经验。
一、SSO 的本质:把认证从应用里抽出来
先建立一个基本认知。传统模式下,每个应用自己干三件事:存用户表、校验密码、维护会话。SSO 做的事就是把前两件抽到统一的认证中心,应用只保留最后一件。
抽出来之后的通用流程(不管什么协议,骨架都一样):
1. 用户访问应用 A,应用发现未登录
2. 应用把用户重定向到认证中心(携带自己的身份标识和回调地址)
3. 认证中心检查:这个浏览器有全局会话吗?
- 没有 → 展示登录页,用户认证(可叠加 MFA)
- 有 → 跳过登录,直接放行
4. 认证中心颁发一张"凭证"(票据/授权码/断言)给应用 A
5. 应用 A 拿凭证向认证中心换取用户身份信息,建立本地会话
6. 用户再访问应用 B → 第 3 步命中全局会话 → 无感登录
安当 ASP 的 SSO 原理就是这套基于票据(Ticket)或令牌(Token)的机制:用户首次认证通过后平台颁发加密令牌,后续访问其他应用时由应用向平台校验令牌有效性,实现无缝跳转。
关键洞察:SSO 的难点从来不是协议实现,而是"如何让 20 个不同年代、不同架构的系统都愿意接受同一个身份来源"。
二、四种协议对比:什么场景用什么
| 维度 | SAML 2.0 | OAuth 2.0 | OIDC | CAS |
|---|---|---|---|---|
| 本质 | 身份联合(认证) | 授权框架(不是认证) | OAuth 2.0 之上的认证层 | 校园/企业经典 SSO 协议 |
| 数据格式 | XML 断言 | JSON + Bearer Token | JSON + JWT(id_token) | XML(票据校验) |
| 传输方式 | 浏览器 POST/Redirect Binding | HTTP 重定向 + 后端换取 | 同 OAuth 2.0 | HTTP 重定向 + 后端校验 |
| 移动端友好 | 差(XML 重、跳转多) | 好 | 好 | 一般 |
| 典型场景 | 企业级 Web 应用、政务系统、传统 SaaS | 第三方应用授权访问 API | 现代 Web/APP/小程序登录 | 高校、老牌企业内网系统 |
| 复杂度 | 高(签名、加密、元数据) | 中 | 中 | 低 |
| 是否携带用户身份 | 是(断言含属性) | 否(只有访问令牌) | 是(id_token 含 claims) | 是(校验返回用户属性) |
选型口诀:
- 新系统、移动端、前后端分离 → 首选 OIDC(授权码模式 + PKCE)
- 传统企业 Web 应用、政务系统、采购的商业 SaaS → SAML 2.0(很多商业软件只支持这个)
- 只需要授权 API 访问,不需要知道用户是谁 → OAuth 2.0
- 存量系统已经在用 CAS → 保留 CAS,别为了统一而重构
- 服务端到服务端调用 → OAuth 2.0 的 Client Credentials 模式
有个常见误区要澄清:OAuth 2.0 不是认证协议 。它解决的是"允许应用 X 访问我在平台上的资源",而不是"我是谁"。拿 OAuth 2.0 直接当登录用(俗称"用授权当认证")会有安全隐患,正确做法是用它的超集 OIDC------多了一个 id_token,里面是签名过的用户身份断言。
ASP 平台对这几种协议都做了支持:OAuth 2.0、OpenID Connect 1.0、SAML 2.0、LDAP、JWT,加上 RADIUS 覆盖网络层,一共 20+ 标准协议。
三、OIDC 接入实战:一个标准 Web 应用的完整流程
以授权码模式为例,这是最推荐的方式(不在浏览器暴露令牌)。
第一步:在 ASP 创建应用 ,拿到 client_id 和 client_secret,配置回调地址。
第二步:应用侧发起认证
http
GET https://asp.company.com/oauth2/authorize
?client_id=oa-system
&response_type=code
&scope=openid profile email
&redirect_uri=https://oa.company.com/sso/callback
&state=a1b2c3d4 # 防 CSRF,必须校验
&nonce=n0nce123 # 防重放,id_token 里会带回
第三步:用户认证完成,ASP 回调
http
GET https://oa.company.com/sso/callback?code=SplxlOBeZQ&state=a1b2c3d4
第四步:后端用 code 换 token
http
POST https://asp.company.com/oauth2/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic base64(client_id:client_secret)
grant_type=authorization_code
&code=SplxlOBeZQ
&redirect_uri=https://oa.company.com/sso/callback
返回:
json
{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "tGzv3JOkF0XG5Qx2TlKWIA",
"id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
}
第五步:校验 id_token(这一步千万别省)
id_token 是一个 JWT,解开后大致长这样:
json
{
"iss": "https://asp.company.com",
"sub": "u-10024",
"aud": "oa-system",
"exp": 1785312000,
"iat": 1785308400,
"nonce": "n0nce123",
"name": "张三",
"preferred_username": "zhangsan",
"email": "zhangsan@company.com",
"dept": "信息中心",
"amr": ["pwd", "otp"]
}
必须校验的项:
- 签名 :用 ASP 的 JWKS 公钥验签(别信
alg: none) - iss:签发者是不是预期的认证中心
- aud:受众是不是自己的 client_id
- exp:是否过期
- nonce:是否与发起时一致
校验通过后,用 sub 作为用户唯一标识建立本地会话。注意:用 sub 而不是用户名或邮箱做主键 ------用户名会改,邮箱会换,sub 不变。
amr 字段(Authentication Methods References)很有用:它告诉应用这次登录用了哪些认证方式。敏感操作可以检查是否包含 otp,不包含就要求重新做强认证(step-up authentication)。
ASP 还提供前端 JavaScript SDK(支持 Vue/React 等主流框架),前后端分离项目可以直接用,省掉手写协议交互的工作。
四、三类业务系统的接入策略
真实企业里,能按标准协议对接的系统通常不到一半。ASP 把应用接入分成三种类型,对应三类现实:
类型一:自建应用(能改造)
管理员在 ASP 手动创建应用,配置应用名称、Client ID、回调地址、认证协议(SAML/OIDC 等),然后由开发团队按协议改造登录逻辑。
适用:自研系统、有源码有团队的系统。改造量一般 1-2 人日。
分两种细分场景:
- 有用户源应用(授权码模式) :应用本地保留用户表,SSO 只负责认证,登录后按
sub或用户名匹配本地用户 - 无用户源应用(隐藏式模式):应用不维护用户表,用户信息完全由 ASP 下发
类型二:第三方应用模板(一键接入)
ASP 内置了预置应用市场,主流 SaaS 和开源系统(金蝶云星空、GitLab、石墨文档等)提供现成模板,无需开发,填几个参数就完成 SSO 配置。
适用:采购的商业软件、常见开源系统。典型对接周期 1 天。
类型三:自动登录应用(表单代填,零改造)
这是解决"老系统接不进来"的杀手锏。
原理:在用户端安装轻量级浏览器插件或客户端代理,当用户访问目标系统登录页时,代理拦截请求,向 ASP 申请解密后的凭据,模拟输入完成登录。
关键特性:
- 全程用户不可见真实密码------凭据在插件内解密后直接填入表单
- 平台可定期轮换目标系统密码,用户完全无感
- 每次代填绑定真实操作人身份,解决共享账号追溯问题
适用:厂商跑路的老 ERP、闭源 C/S 系统、多人共用的电商后台、外部供应商门户。
一个真实案例:某知名电商公司运营多个平台店铺,后台系统只有少量共享账号,运营、客服、仓管多岗位共用,密码记在 Excel 和聊天工具里。部署 ASP + SYP 密码保险箱后,密码集中托管、后台自动代填、明文对使用者完全不可见,每次登录绑定真实操作人。效果:100% 明文密码隔离,人均登录效率提升 30%,离职即时撤权无需改共享密码。
五、几个必须提前想清楚的设计问题
1. 单点登出(SLO)怎么做
用户在 ASP 退出后,其他应用的本地会话怎么办?三种做法:
| 方案 | 机制 | 优缺点 |
|---|---|---|
| 前端通道登出 | 认证中心页面嵌入各应用的登出 iframe | 简单,但受第三方 Cookie 限制,可靠性下降 |
| 后端通道登出 | 认证中心向各应用推送登出通知 | 可靠,但应用要实现接收端点 |
| 短会话 + 令牌校验 | 应用本地会话设短,靠令牌续期时发现已登出 | 最简单,代价是有窗口期 |
实践建议:对安全要求高的应用用后端通道登出;一般应用用"短会话 + 令牌校验"就够。
2. 会话有效期怎么配
三层会话要分别设定:
- 认证中心全局会话:8 小时(一个工作日)
- 应用本地会话:30 分钟-2 小时
- access_token:1 小时;refresh_token:8 小时
原则:越靠近敏感资源的会话越短。财务、人事系统的本地会话建议 15-30 分钟。
3. 用户属性怎么映射
ASP 下发的字段和应用本地字段名往往对不上。ASP 支持应用账号自定义映射,在平台侧配置映射规则,避免改造应用。
4. 首次登录用户怎么处理
用户在 ASP 有身份,但应用本地还没记录,两种策略:
- JIT Provisioning(即时开通):首次 SSO 登录时按断言里的属性自动建本地用户
- 预同步:通过 API 或 LDAP 提前把用户批量灌进应用
大部分场景推荐 JIT,减少同步链路。
六、常见问题
Q:SSO 上线后,认证中心挂了是不是全公司都进不去?
这是必须回答的风险。对策:双机热备 + 集群部署(Keepalived VIP 漂移、PostgreSQL 主从复制),RTO < 30 秒、RPO ≈ 0;关键应用保留本地应急登录入口,只给少数管理员并强审计。
Q:SAML 断言签名一直校验失败怎么排查?
按顺序查:① IdP 元数据里的证书和实际签名证书是否一致;② 断言是整体签名还是 Response 签名,SP 侧配置要匹配;③ 时钟偏差(SAML 对 NotBefore/NotOnOrAfter 敏感,NTP 必须同步);④ XML 规范化方式(c14n)是否一致。
Q:能不能既做 SSO 又保留原来的账号密码登录?
技术上可以(双入口),但强烈建议过渡期后关闭本地登录入口。否则 SSO 的审计和权限回收能力形同虚设------离职员工照样能走本地入口进去。
Q:JWT 用对称密钥(HS256)还是非对称(RS256)?
多应用场景一律用 RS256。HS256 需要把密钥分发给每个应用,任何一个应用泄露密钥,攻击者就能伪造所有应用的令牌。RS256 只分发公钥,安全边界清晰。
Q:SSO 会降低安全性吗?"一把钥匙开所有门"?
会集中风险,所以必须配套两件事:① 认证中心强制 MFA(密码 + OTP/UKey/FIDO2);② 敏感应用做 step-up 认证,进入时要求重新做强认证。做到这两点,SSO 的整体安全性远高于"每个系统各自弱口令"的状态。
写在最后
SSO 项目的成败,技术占三成,节奏占七成。
我的建议是:先接 5 个用户量最大、改造最容易的系统(通常是 OA、门户、邮箱、报销、考勤),让全员在两周内感受到"少记 5 个密码"的好处。有了群众基础,再去啃 ERP、去啃那个厂商已经不在了的老系统。
协议选型反而是最简单的部分:新系统 OIDC,商业软件 SAML,老系统表单代填。三条路径覆盖 95% 的情况。
本文技术内容参考《安当 ASP 身份认证服务平台技术白皮书 V4.0》。ASP 支持 OAuth 2.0 / OIDC / SAML 2.0 / LDAP / JWT 等 20+ 标准协议,提供预置应用市场与免改造表单代填能力。