4. SCIM 身份源与目标系统建模

在 SCIM 工程中,最容易出问题的往往不是协议本身,而是“谁说了算”。一个企业里通常同时存在 HR 系统、IdP(如 Okta、Azure AD、Keycloak)和大量 SaaS 应用。如果不在建模阶段明确每个系统的角色,就会出现同一用户在 HR 已离职、IdP 仍启用、SaaS 仍可登录的割裂状态。本节要解决的核心问题就是:把 HR 系统建模为权威源(Authoritative Source),把 IdP 建模为身份源与分发中枢,把 SaaS 应用建模为目标系统(Target),并在此基础上设计属性映射与转换规则。

一、三种角色的职责边界

HR 系统是权威源。它掌握员工的生命周期事实:入职、转岗、离职、组织归属、工号、成本中心。这些数据是“事实”,不应由下游系统反向修改。因此 HR 系统通常只作为 SCIM 的“上游数据提供者”,通过定时同步或事件推送把用户数据交给 IdP,而不是直接对每个 SaaS 应用发起 SCIM 请求。

IdP 是身份源与分发中枢。它从 HR 接收权威数据,补充认证相关属性(登录名、邮箱、MFA 状态),再以 SCIM 服务端(Service Provider)的身份向各 SaaS 应用下发用户与组。IdP 是 SCIM 请求的发起方(Client),SaaS 应用是接收方(Server)。

SaaS 应用是目标系统。它消费 SCIM 数据,维护本地账号,并可能回写少量状态(如 lastLogin)。目标系统不应成为属性的权威来源,否则会形成循环依赖。

判断角色的一句话原则:谁产生“雇佣事实”,谁就是权威源;谁发起 SCIM 请求,谁就是身份源;谁接收并落地账号,谁就是目标系统。

二、整体数据流与建模关系

下图展示了 HR、IdP 与多个 SaaS 目标之间的数据流方向、SCIM 端点角色以及属性映射发生的位置。注意箭头方向:HR→IdP 是数据汇聚,IdP→SaaS 是 SCIM 下发,SaaS 的少量回写只用于状态观测,不参与权威判定。

HR 系统 权威源 employeeId / 部门 入职 / 离职状态 成本中心 / 经理 IdP 身份源 SCIM Client / 分发中枢 用户主数据 + 认证属性 组 / 角色 / 应用分配 属性映射引擎 SCIM 2.0 请求构造 同步策略 / 过滤规则 /Users /Groups /Bulk SaaS 目标 A SCIM Server userName / emails active / groups SaaS 目标 B SCIM Server externalId 映射 自定义扩展属性 SaaS 目标 C SCIM Server 仅支持 PATCH 无 /Bulk 端点 定时/事件同步 CSV / API / 中间表 SCIM 2.0 SCIM 2.0 SCIM 2.0 状态回写 映射发生位置:IdP 侧完成 HR 字段 → SCIM 属性的转换,再按目标能力裁剪。 回写仅用于观测(如 lastLogin),不参与权威判定,避免循环依赖。

三、属性映射与转换规则设计

SCIM 的核心属性集包括 userName、name.givenName、name.familyName、emails、active、externalId、groups。HR 系统的字段命名往往与 SCIM 不一致,需要在 IdP 侧建立映射表。以下是一份可直接参考的映射与转换规则示例(示例参数,非实测结果):

HR 字段SCIM 属性转换规则目标差异处理
emp_noexternalId直接映射,作为幂等键目标 B 要求 externalId 唯一
login_nameuserName小写化 + 去空格目标 C 不允许大写
emailemails[type eq "work"].value直接映射,primary=true目标 A 仅接受 work 类型
statusactive在职→true,离职→false离职时先 PATCH active=false
dept_codegroups[].display查部门字典转为组名目标 B 用组 ID 而非名称
hire_dateurn:ietf:params:scim:schemas:extension:enterprise:2.0:User:hireDate格式化为 ISO 8601仅目标 A 支持扩展

转换规则要遵循三条原则。第一,幂等键优先:externalId 应绑定 HR 的工号,确保重复同步不会创建重复账号。第二,单向权威:active、userName 等关键属性只允许从 IdP 流向 SaaS,禁止反向修改。第三,目标能力裁剪:不同 SaaS 对 SCIM 的支持程度不同,映射时要按目标能力过滤,例如目标 C 不支持 /Bulk,就应改为逐条请求。

四、同步策略与冲突处理

建模完成后,需要确定同步节奏。常见做法是:HR 每日全量 + 关键事件增量(入职、离职、转岗)触发 IdP 更新,IdP 再以 5~15 分钟为周期向 SaaS 增量同步。离职场景建议采用“先禁用、后删除”的两段式:先 PATCH active=false,保留账号用于审计,30 天后再 DELETE。

冲突处理要明确优先级:当 HR 与 IdP 数据不一致时,以 HR 为准;当 IdP 与 SaaS 不一致时,以 IdP 为准。若目标系统返回 409 Conflict,说明 externalId 或 userName 已存在,此时应查询该资源并执行 PATCH 而非 POST,避免重复创建。

常见误区:把 SaaS 应用当作权威源反向覆盖 IdP。一旦形成双向写入,离职状态可能被旧数据“复活”,导致账号无法及时回收。

五、建模检查清单

  • 是否明确 HR 为唯一权威源,且下游系统无写权限?
  • IdP 是否持有 SCIM Client 凭据,并按目标分别配置端点与认证方式?
  • 每个目标系统是否确认了支持的 SCIM 版本、端点(/Users、/Groups、/Bulk、/Me)与 PATCH 能力?
  • 属性映射表是否覆盖必填属性,并标注了转换函数与目标差异?
  • 是否定义了幂等键(externalId)与冲突处理策略?
  • 离职流程是否采用“禁用→延迟删除”,并保留审计窗口?