跳到正文
LEo的网络日志
返回

零基础看懂 ldap、业务系统和 keycloak 的用户管理

第一次接触用户管理时,我最困惑的不是某个配置项,而是下面几个问题:

要回答这些问题,先记住一个最重要的结论:

登录和业务授权是两件事。keycloak 主要解决“你是谁”,应用平台最终决定“你能做什么”。

本文用一个虚构的公司作为固定示例,把 ldap、业务系统、keycloak 和应用平台之间的关系完整走一遍。实际系统的接口和数据归属可能不同,但判断方法相同。

先把四个系统翻译成人话

假设公司有员工小王,他要登录“研发应用平台”管理项目。

系统可以把它理解成主要保存什么不应该替谁做决定
ldap公司花名册和账号库账号、姓名、邮箱、密码校验信息、是否在职不负责判断小王能否管理某个项目
业务系统工作安排表部门、岗位、所属项目、业务角色通常不负责给所有应用签发登录令牌
keycloak统一门卫和临时通行证签发处登录会话、客户端、基础角色、必要的用户映射不会凭空知道业务系统里的项目关系
应用平台真正提供功能的办公区平台用户、项目成员关系、资源权限不应自己保存或校验 ldap 密码

可以先把它们连成下面这张图:

                   登录链路
浏览器 ──> 应用平台 ──> keycloak ──> ldap
  ^              验证令牌 <── 签发令牌   │
  └──────────────── 登录成功 ────────────┘

                   授权链路
业务系统 ──同步部门、项目、角色──> 应用平台权限库

                                └──决定页面和接口能不能访问

注意,这里其实有两条独立链路:

  1. 登录链路:应用平台、keycloak 和 ldap 配合确认“小王是谁”。
  2. 授权链路:业务系统把项目和角色关系交给应用平台,应用平台判断“小王能做什么”。

只要把这两条链路分开,后面的配置就容易理解了。

第一步:小王入职,谁创建什么

管理员先在 ldap 中创建公司账号:

账号:xiaowang
姓名:王小明
邮箱:xiaowang@example.com
状态:在职
密码:只由身份目录安全保存和校验

业务管理员再在业务系统中安排工作:

员工:xiaowang
部门:示例部门
项目:示例项目
业务角色:项目管理员

这不是重复保存同一份数据,而是保存两类不同的事实:

ldap 的事实:xiaowang 是一个有效的公司账号
业务系统的事实:xiaowang 是示例项目的管理员

那么 keycloak 和应用平台里的用户从哪里来?常见做法有两种:

无论采用哪一种,通常都不会同步密码。密码仍由 ldap 校验。

第二步:小王第一次登录,系统到底做了什么

假设 keycloak 已经配置了 ldap 用户联合,应用平台也已经在 keycloak 中登记为一个客户端。

小王打开应用平台后,会发生下面 8 步:

1. 小王访问应用平台
2. 应用平台发现浏览器还没有登录
3. 应用平台把浏览器跳转到 keycloak
4. 小王在 keycloak 登录页输入账号和密码
5. keycloak 到 ldap 校验账号、密码和账号状态
6. ldap 告诉 keycloak:验证成功
7. keycloak 给应用平台签发一个有时效的令牌
8. 应用平台验证令牌后,认出当前用户是 xiaowang

其中最容易误解的是第 5 步。页面虽然是 keycloak 的,但在这个示例中,真正校验密码的是 ldap:

小王输入密码

keycloak 拿这次登录请求去询问 ldap

ldap 只回答“成功”或“失败”

keycloak 根据结果决定是否签发令牌

应用平台不会拿到小王的密码,也不需要连接 ldap。它只信任 keycloak 签发的令牌。

令牌可以粗略理解成下面这样一张有过期时间、且无法随意伪造的通行证:

{
  "sub": "用户的稳定唯一标识",
  "preferred_username": "xiaowang",
  "email": "xiaowang@example.com",
  "roles": ["platform-user"],
  "exp": "过期时间"
}

应用平台收到令牌后,还必须检查:

所以,keycloak 不是把“登录成功”口头告诉应用平台,而是签发一个应用平台能够验证的令牌。实际通常使用 openid connect,它建立在 oauth 2.0 之上。

第三步:登录成功后,应用平台怎样知道小王能管理哪个项目

仅仅登录成功,只能证明当前用户是 xiaowang,不能证明他是“示例项目”的管理员。

应用平台还要查询自己的权限数据:

令牌告诉应用平台:当前用户是 xiaowang

应用平台查询权限库:xiaowang 属于哪些项目?

查询结果:示例项目,角色为管理员

应用平台允许他进入示例项目的管理页面并调用管理接口

这里要特别注意:keycloak 不会自动读取业务系统的数据库,也不会自动理解“项目管理员”的业务含义。

业务系统中的关系必须通过双方明确设计的方式传给应用平台,例如:

业务系统发现小王被加入示例项目

调用应用平台提供的成员同步接口

应用平台保存:xiaowang + 示例项目 + 管理员

小王访问项目时,应用平台查询这条关系并放行

也可以由应用平台定时读取业务系统提供的受控接口,或者由消息系统传递变更事件。无论用哪种方式,都应该有明确的字段映射、失败重试和审计记录,而不是让两个系统直接修改彼此的数据库。

为什么不把所有项目权限都放进 keycloak 令牌

把少量、稳定、多个应用都能理解的基础角色放进令牌通常比较合适,例如:

platform-user
platform-admin
auditor

但下面这类数据更适合由应用平台维护:

小王是项目 a 的管理员
小王是项目 b 的只读成员
小王只能操作项目 c 中的某几个资源

原因很直观:

因此,一个实用的分工是:

keycloak 令牌:用户身份 + 少量基础角色
应用平台权限库:项目、资源、成员关系等详细业务权限

这不是唯一方案,但很适合帮助初学者理解边界。

业务系统是否参与每次登录

在本文的示例架构中,不参与

登录时的实时调用是:

应用平台 → keycloak → ldap

业务系统只在用户的部门、项目或角色发生变化时,把业务关系同步给应用平台。它不需要在每次登录时都在线。

如果某套系统把业务系统本身建设成了身份提供方,那么 keycloak 也可以把浏览器跳转到该系统登录。这是另一种架构:

应用平台 → keycloak → 业务身份提供方 → ldap

两种架构都可能成立,但不要混在一张流程图里。判断现场系统属于哪一种,只需查看 keycloak 配置的是“ldap 用户联合”,还是“外部身份提供方”。

管理员修改小王的角色后,什么时候生效

假设小王从“项目管理员”变成“普通成员”。完整变化过程是:

1. 管理员在业务系统修改小王的项目角色
2. 业务系统通过接口、事件或定时任务同步变更
3. 应用平台更新自己的项目成员关系
4. 小王再次调用项目接口
5. 应用平台读取最新权限,只允许普通成员的操作

如果变化的是 keycloak 令牌中的基础角色,还要考虑旧令牌:它在过期前仍可能带着旧角色。因此需要根据风险选择短令牌有效期、令牌刷新、会话撤销,或者让应用平台对高风险操作实时复核权限。

这也解释了为什么“后台已经改了角色,页面却没有立刻变化”:可能是同步任务还没执行,也可能是旧令牌或应用缓存还没失效。排查时应依次确认:

权威数据源是否已经修改

同步是否成功

应用平台权限库是否已经更新

旧令牌或缓存是否仍在使用

小王离职后,又会发生什么

小王离职时,至少要处理两条链路:

身份链路:ldap 停用账号 → keycloak 不再签发新令牌
授权链路:业务系统移除关系 → 应用平台撤销项目和资源权限

仅仅停用 ldap 账号,并不代表已经签发的旧令牌会立即消失;仅仅删除应用平台的项目权限,也不代表账号不能登录。因此高风险系统还需要撤销 keycloak 会话、缩短令牌有效期,并确保应用平台每次访问都执行权限检查。

真正需要配置和开发哪些东西

把前面的原理落到实施工作上,通常分为三组。

keycloak 管理员配置

应用平台开发

业务系统开发

keycloak 的配置只能完成统一身份和令牌能力。项目成员同步、业务角色解释、接口权限判断仍然需要业务系统和应用平台配合开发。

用三个问题判断一套设计是否清楚

面对真实系统时,可以直接问:

  1. 谁校验密码? 本文示例是 ldap。
  2. 谁签发应用平台信任的令牌? 本文示例是 keycloak。
  3. 谁对某个项目或资源的操作做最终决定? 本文示例是应用平台。

如果这三个问题没有明确答案,系统边界通常还没有设计清楚。

最后用一句话串起来

小王登录时,keycloak 请 ldap 验明身份并给他一张限时通行证;小王操作项目时,应用平台再根据业务系统同步来的项目关系,决定这张通行证能打开哪扇门。

所谓“用户管理集成”,不是把所有用户数据都复制到 keycloak,而是让身份、令牌和业务权限各有权威来源,再通过标准登录协议和受控同步接口把它们连起来。



上一篇
chatgpt小贴士(九)
下一篇
chatgpt小贴士(十)