LabHub
学习 学习路径 课程

企业认证对接

身份证与门禁卡 — 认证方式的全景

在 LabHub 中继续学习

一句话总结

SI 项目中的认证之所以困难,不是因为认证本身难,而是因为客户已经有一套认证体系,我们的系统必须嵌入其中。

概念图: 客户已经有一套认证体系 · 认证体系早已存在 · 目录协议 · 认证联邦(SSO)协议

为什么 SI 项目的认证很难

单独开发一个新系统时,认证并不复杂:把用户名与密码存进数据库即可。SI 项目困难,是因为认证体系早已存在

客户现场通常已经有以下系统。

你开发的系统必须插入这些系统之间。因此,“接一下登录”这一行需求,实际可能需要两个月。

不要混淆这四种概念

名称 是什么 一句话类比
LDAP 保存用户与组织信息的目录协议 电话簿
SAML 2.0 基于 XML 的认证联邦(SSO)协议 纸质身份证
OIDC 构建在 OAuth 2.0 之上的认证联邦协议 数字身份证
OAuth 2.0 **授权(权限委托)**框架 酒店房卡

最重要的是区分最后两项。

OIDC/SAML 用来签发身份证,OAuth 2.0 用来签发酒店房卡。 房卡只说明“这张卡可以打开 305 房和健身房”, 并不说明持卡人是谁。

由此会产生一个著名反模式:用访问令牌判断登录身份。 访问令牌中关于“签发给谁”的验证依据(aud)可能不存在或约束宽松。攻击者可以拿其他应用的令牌来通过验证,形成令牌替换攻击。判断登录身份必须使用 ID 令牌。

LDAP 是认证协议吗

只说对了一半。LDAP 是目录查询协议,也能通过 bind 操作验证密码,因此“LDAP 认证”这个说法成立。但这意味着应用程序直接接收密码,再去询问 LDAP,并不是 SSO;每个应用仍有自己的登录页面。

实际项目通常这样组合。

[사용자] --로그인--> [IdP(Keycloak 등)] --bind/조회--> [AD / LDAP]
     |                      |
     |<---- ID 토큰 --------|
     v
[우리 시스템]  ← 토큰만 검증. 비밀번호를 절대 보지 않는다

关键收益在于我们的系统从不接触密码。看不到密码,就不会成为密码泄露事故的责任主体。

传统请求头认证——大型企业与金融内网的现实

运行了 15 年的 WebSSO 产品(SiteMinder 系列)通常这样工作:在 Web 服务器上安装代理,认证完成后把用户信息写入 HTTP 请求头,再传给后端应用。

SM_USER: jdoe
SM_USERDN: uid=jdoe,ou=people,dc=example,dc=com
SM_USERGROUPS: hr-staff^payroll-admin

后端 Java 应用在过滤器中读取 request.getHeader("SM_USER") 完成登录。方式简单,几乎不需要改应用,因此数百个应用可能都采用这种结构。

问题也很明确:应用无条件信任请求头,意味着只要存在一条绕过代理、直接访问应用的路径,认证就会立刻被绕过。

curl -H "SM_USER: ceo" -H "SM_USERGROUPS: payroll-admin" \
     http://hr-app.internal:8080/hr/payroll/list

现实中确实存在这一行就能成功的系统,因此必须实施三项控制。

  1. 网络隔离——除网关外,任何来源都不能访问应用端口
  2. 在边缘删除请求头——无条件删除外部传入的 SM_*,再重新写入可信值
  3. 网关与应用之间相互认证——使用 mTLS 或共享秘密

这并不是过时问题。现代反向代理认证(例如 oauth2-proxy)也采用完全相同的结构。 凡是通过请求头传递身份的配置,都需要同样的控制。

请求头方式还有一个解析陷阱:SM_USERGROUPS 的分隔符是脱字符(^。如果代码假设使用逗号分隔,就会把整串内容当成一个组,导致权限全部丢失。制作迁移清单时,不仅要调查请求头名称,还要调查值的格式

什么时候使用哪一种方式

场景 选择
新建 Web/移动应用,且我们能控制 IdP OIDC(Authorization Code + PKCE)
对方是大型企业/公共机构,已有 SAML IdP SAML 2.0
只需查询内部账户信息与组 LDAP 查询(认证交给 IdP)
服务间通信(批处理、集成) OAuth 2.0 client_credentials
100 个运行 15 年的应用短期无法修改 基于代理的请求头注入 + 上述三项控制

最后一行正是 SI 的现实。理想答案是全部使用 OIDC,但在应用无法修改时,还需要真正能运行的方案。此时让代理代为处理 SSO,再通过请求头传给应用,同时必须实施上述三项控制。

最后,不要忘记批处理与服务账户

SSO 迁移项目反复出现一种事故:只有月末/季末才发生认证失败。

常见原因是夜间批处理或集成程序一直在模仿真人登录页面通过认证。如果迁移范围只包含人员账户,就会漏掉它们;而批处理只在月末运行,于是迁移后连续三周看似毫无问题,随后突然失败。

清单调查中必须问一个问题:

“是否有非人员主体也要通过这套认证?”

如果答案是“没有”,十有八九只是尚未找到。

在实际项目中

“接一下登录”从一行需求变成两个月工作的过程,通常如下。

首先,接到哪里没有确定。人力系统是人员源头,但 AD 负责登录,协同办公是实际入口,最近又单独接入了 IdP。不同负责人对“公司账户”会给出不同答案。

接着遇到传统请求头认证。前端 WebSSO 把用户 ID 放进 HTTP 请求头,这套系统已经运行 15 年,不能修改。此时必须确认一件事:能否从外部直接设置这个请求头。如果代理不覆盖请求头,任何人都可以冒用他人的 ID。

最后遗漏的是批处理与服务账户。只围绕人员账户设计并上线后,才开始决定夜间批处理凭什么连接。