查看源文件

ForgeRock 身份平台工作原理:从一次登录说起

打开公司的报销系统,浏览器跳到统一登录页,输完密码再收一条验证码,就回到了报销页面;接着打开考勤系统,这次没有再要求登录。新同事入职第一天就能登录邮箱。这些日常体验背后,通常有一套身份平台在工作。

ForgeRock 身份平台就是其中常见的一种。本文沿着“一次访问”这条线,把平台的各个组件串起来:请求先被谁拦下,登录时经过哪些检查,登录结果存在哪里,应用怎么判断令牌的真假,账号又是从哪里来的。读完以后,再看平台的配置界面和日志,就能知道每一块在整个流程里的位置。

一、身份平台要回答的两个问题

不管登录系统还是访问应用,身份平台都在回答两个问题:

  1. 你是谁? 这是认证(Authentication),用密码、验证码等方式确认用户身份。
  2. 你能访问什么? 这是授权(Authorization),在确认身份之后,判断这个用户能不能访问某个地址、做某个操作。

如果每个应用各自实现这两件事,用户就要记住很多套账号,管理员也要在很多系统里分别开号、删号。身份平台把认证、授权和账号管理集中到一处,各个应用只负责接入。

关于名字

ForgeRock 原本是一家独立公司。2023 年 8 月,Thoma Bravo 完成对 ForgeRock 的收购,并将它并入旗下的 Ping Identity。从 2024 年初开始,产品陆续改名:

原名现名
ForgeRock Access Management(AM)PingAM
ForgeRock Identity Management(IDM)PingIDM
ForgeRock Directory Services(DS)PingDS
ForgeRock Identity Gateway(IG)PingGateway
ForgeRock Identity CloudPingOne Advanced Identity Cloud

自建部署的这一套产品,现在统称为 Ping Advanced Identity Software。改名不影响工作原理,下文仍沿用 AM、IDM、DS、IG 这些简称,它们也是配置和日志里最常见的叫法。

二、平台全景:四个组件各管什么

四个组件的分工如下:

组件角色主要职责
IG(身份网关)守门人作为反向代理挡在应用前面,检查每个请求,执行访问策略
AM(访问管理)验证中心认证用户、管理会话、签发令牌、做授权决策
DS(目录服务)档案柜存放身份数据、平台配置和令牌
IDM(身份管理)账号工厂从人事等系统同步人员信息,自动开通和更新账号;按配置删除或解除关联

除了 IG,平台还提供 Web Agent 和 Java Agent。它们装在 Web 服务器或 Java 应用容器里,作用和 IG 相同,都负责在应用门口执行策略。

用一句话概括四者的关系:IDM 造身份,DS 存身份,AM 验身份,IG 守大门。 下面跟着一次访问,依次看它们如何配合。

三、一次访问的完整旅程

第 1 步:网关拦下没有登录的请求

用户在浏览器里打开一个受保护的应用时,请求不会直接到达应用,而是先经过 IG。

IG 是一个反向代理,介于外部客户端和内部服务之间。它对请求的处理由“路由”决定,每条路由由一串过滤器(Filter)和处理器(Handler)组成,请求按顺序经过它们。

IG 首先检查请求里有没有有效的会话。第一次访问时还没有登录,自然没有会话。IG 不会放行,而是把浏览器重定向到 AM 的登录页面。

第 2 步:在 AM 里走完一棵认证树

AM 里的登录流程叫认证树,新版界面里也叫 Journey。一棵树由若干节点组成,每个节点完成一件事,并根据结果走向不同的出口。

以“用户名、密码,再加多因素认证”这个常见流程为例:

  1. 收集用户名:节点提示用户输入用户名。
  2. 收集密码:节点提示用户输入密码。
  3. 核对密码:Data Store Decision 节点到身份库(通常是 DS)里核对用户名和密码。它有两个出口:核对成功走 True,通常连到成功节点或下一步;核对失败走 False,通常连到失败节点。
  4. 多因素认证:再加一道验证,可选的节点包括一次性验证码(OATH Token Verifier)、推送通知(Push Sender)和 WebAuthn 等。

全部通过以后,AM 为这次登录创建会话。实际的节点并不限于成功和失败两种出口,一个节点可以有多个出口,管理员可以按业务需要拼出更复杂的流程。

AM 还用**领域(Realm)**组织配置和身份,一个领域相当于一个管理单元。默认的顶级领域是 /。

第 3 步:会话存在哪里

登录成功后,浏览器拿到一个 SSO Cookie,默认名叫 iPlanetDirectoryPro。官方文档要求在生产环境修改这个名字。

Cookie 对应的会话有两种保存方式:

  • 服务端会话:会话保存在 CTS(Core Token Service,核心令牌服务)里,CTS 的数据存放在 DS 上。
  • 客户端会话:会话本身是一个经过签名(也可以加密)的 JWT,直接放在 Cookie 里。

使用服务端会话时,CTS 就成了关键依赖。CTS 里的会话数据一旦丢失,用户就必须重新登录。

第 4 步:带着会话回到网关,做策略评估

浏览器带着 Cookie 再次访问应用,IG 这次能确认会话有效。不过“已登录”不等于“能访问”,IG 还会请 AM 做一次策略评估:这个用户能不能访问这个地址?

在这个分工里:

  • AM 是策略决策点(PDP):根据配置好的策略给出“允许”或“拒绝”。评估接口按领域划分,形如 /json/realms/root/realms/<realm>/policies?_action=evaluate。
  • IG 是策略执行点(PEP):通过 PolicyEnforcementFilter 向 AM 发起评估,再按结果放行或拦截。前面提到的 Web Agent 和 Java Agent 也是策略执行点。

AM 返回“允许”后,IG 才把请求转发给后端应用。至此,一次完整的访问结束。

四、给应用和 API 的令牌:OAuth 2.0 与 OpenID Connect

上面的会话 Cookie 主要服务浏览器场景。面对现代 Web 应用、移动应用和 API 调用,AM 还承担两个角色:OAuth 2.0 授权服务器和 OpenID Connect(OIDC)提供方。它签发三类令牌:

令牌用途
访问令牌(Access Token)调用 API 时出示,证明有权访问
ID 令牌(ID Token)告诉应用“这个用户是谁”
刷新令牌(Refresh Token)访问令牌过期后,用来换取新的令牌

把令牌理解成盖了章的通行证

ID 令牌是一个签名的 JWT,由三段组成:

  1. 头部:说明令牌类型和签名算法。
  2. 内容:记录用户是谁、令牌给谁用、什么时候过期等信息。
  3. 签名:相当于通行证上的那枚章。

盖章和验章靠的是一对密钥:

  • 私钥只在 AM 手里,用来给令牌签名,也就是盖章。
  • 公钥对外公开,AM 把它发布在 JWKS 端点 /oauth2/connect/jwk_uri 上,谁都能取。

应用收到 ID 令牌后,拿公钥核对签名。对得上,就说明令牌确实由 AM 签发、内容没有被改过,整个过程不需要再问 AM。

也可以直接问 AM

本地验签只能说明令牌是真的,不能反映它是否已经被撤销。对访问令牌,应用还可以调用内省端点 /oauth2/introspect(遵循 RFC 7662),直接向 AM 查询它当前是否有效。

AM 的 OAuth 2.0 令牌同样有两种形态:默认的服务端令牌保存在 CTS 中;客户端令牌则是 JWT。

一个容易忽略的安全点

AM 默认用一个测试密钥给 ID 令牌签名。上线前必须换成自己的密钥。AM 支持密钥映射和轮换,可以定期更换签名密钥。

五、DS:所有身份数据的档案柜

前面几步里,核对密码要查 DS,会话和令牌要存进 CTS,而 CTS 也建在 DS 上。DS 是整个平台的底座。

它是什么

DS 是一个目录服务器,支持 LDAPv3 和 REST 访问,和大家熟悉的 AD 属于同一类东西。目录里的每条记录叫一个条目,每个条目都有唯一的名字,叫 DN(Distinguished Name),例如:

uid=jdoe,ou=people,dc=example,dc=com

可以把目录想象成一个卡片柜,每个条目就是柜子里的一张索引卡。

它存什么

在 ForgeRock 平台里,DS 通常承担以下几类存储,DS 的安装程序也为它们分别准备了配置模板(setup profile):

  • 身份库:存放用户账号,供 AM 认证时查询。
  • 配置库:存放 AM 的配置。
  • CTS 令牌库:存放会话和令牌。
  • IDM 存储库:存放 IDM 管理的用户等数据。IDM 也可以改用 MySQL、PostgreSQL 等关系数据库。

多台 DS 之间怎么同步

生产环境一般部署多台 DS 副本。应用可以写入任意一台副本,改动会复制到其他副本,经过一段时间后各副本数据一致。官方文档把这种复制描述为“最终收敛”。

“最终”意味着中间有延迟。复制延迟变大时,另一台副本上可能暂时还是旧数据。如果负载均衡没有做会话亲和,AM 可能刚把数据写到一台副本,下一次请求却从另一台读到旧值,表现得像“忘了”刚才的更新。所以官方建议持续监控复制延迟,发现延迟过大且持续不降时要及时处理。

六、IDM:账号最初从哪里来

DS 里的账号,最初是怎么来的?答案是 IDM。

人事系统说了算

在多数企业里,人员信息以人事系统为准,它是权威数据源。IDM 的工作分三步:

  1. 读取源系统:通过连接器读取人事系统里的员工信息。连接器来自 ICF(OpenICF)框架,支持 LDAP/AD、CSV 文件、脚本化 REST 和 SQL 等多种系统。
  2. 按规则转换:根据**映射(Mapping)**规则,把源数据转换成平台里的受管用户(managed/user)。
  3. 写入目标系统:把账号开通到 AD 等目标系统,受管用户本身则保存在 IDM 的存储库里,比如 DS。

对账:逐条比对,决定怎么处理

**对账(Reconciliation)**会逐条比较源系统和目标系统的数据,把每条记录归入一种“情形”(Situation),再执行对应的动作。最常见的三种情形如下:

情形含义默认动作
ABSENT人事里有这个人,但还没有关联的账号CREATE(新建账号)
CONFIRMED人事记录已经和账号关联上UPDATE(按人事信息更新账号)
SOURCE_MISSING账号还在,但人事里已经没有这个人EXCEPTION(只报异常)

第三种情形需要特别注意:人事里删了人,IDM 默认不会自动删除账号,只会报异常。如果希望离职员工的账号被删除或解除关联,需要把动作配置成 DELETE 或 UNLINK。

LiveSync:日常只同步改动

全量对账适合首次导入或定期核对。日常的入职、调岗、离职,则靠 LiveSync 处理:IDM 从源系统增量获取变化,只把改动同步过去。这样账号的开通和更新能随人员变动及时完成。

七、日常监控与排障

平台提供的观测手段

  • 指标:各组件都以 Prometheus 格式暴露监控指标。具体路径随版本变化,例如 AM 8 已弃用 /json/metrics/prometheus,改为 /metrics/prometheus/0.0.4。配置采集前请查对应版本的文档。
  • 健康检查:AM 提供存活检查 /json/health/live 和就绪检查 /json/health/ready。旧的 isAlive.jsp 已经弃用。
  • 目录监控:DS 可以通过 LDAP 查询 cn=monitor 获取监控数据。
  • 审计日志:AM 的审计日志分为 access、activity、authentication 和 config 四类。

用事务 ID 串起一次请求

一次访问会经过 IG、AM 和 DS,排障时最怕各组件的日志对不上。ForgeRock 用 X-ForgeRock-TransactionId 请求头在组件之间传递事务 ID,同一次请求在各组件的审计日志里带着同一个 ID,就能串成一条线。

这个功能默认没有打开,需要显式开启信任:

  • 在 AM 等组件中,将 org.forgerock.http.TrustTransactionHeader 设为 true(默认为 false)。
  • DS 还需要设置 trust-transaction-ids:true。

出问题时先查这四件事

结合前面讲过的依赖关系,下面四项最值得优先排查:

  1. DS 和 CTS 的连通性:认证要查身份库,服务端会话存在 CTS。CTS 数据丢失会导致用户被迫重新登录。
  2. 服务器时钟是否同步:令牌和断言都有时间限制,时钟偏差会影响校验。官方建议使用 NTP,SAML 也有专门的断言时间偏差(Assertion Time Skew)设置。
  3. 签名密钥和证书是否过期:密钥要按计划映射和轮换。DS 还提供证书到期相关的监控指标。
  4. 复制是否延迟:持续偏大的复制延迟可能让 AM 读到旧数据。

结语

回到开头的场景:浏览器被带到统一登录页,是 IG 发现没有会话;输密码、收验证码,是 AM 在执行认证树;之后打开别的系统不用再登录,是因为会话已经保存在 DS 的 CTS 里;新同事入职就能用邮箱,靠的是 IDM 把人事系统的变化同步到各个系统;离职员工的账号要不要删除,则取决于 IDM 的对账配置。

把这条线记住,再看 ForgeRock(或者现在的 Ping)平台里的任何一项配置,都能找到它在整个流程中的位置:IDM 造身份,DS 存身份,AM 验身份,IG 守大门。