第一次接触用户管理时,我最困惑的不是某个配置项,而是下面几个问题:
- 用户到底创建在哪里?
- keycloak 会不会自动知道用户属于哪个项目?
- 用户登录应用平台时,业务系统有没有参与?
- 管理员修改角色后,为什么不能立刻看到效果?
要回答这些问题,先记住一个最重要的结论:
登录和业务授权是两件事。keycloak 主要解决“你是谁”,应用平台最终决定“你能做什么”。
本文用一个虚构的公司作为固定示例,把 ldap、业务系统、keycloak 和应用平台之间的关系完整走一遍。实际系统的接口和数据归属可能不同,但判断方法相同。
先把四个系统翻译成人话
假设公司有员工小王,他要登录“研发应用平台”管理项目。
| 系统 | 可以把它理解成 | 主要保存什么 | 不应该替谁做决定 |
|---|---|---|---|
| ldap | 公司花名册和账号库 | 账号、姓名、邮箱、密码校验信息、是否在职 | 不负责判断小王能否管理某个项目 |
| 业务系统 | 工作安排表 | 部门、岗位、所属项目、业务角色 | 通常不负责给所有应用签发登录令牌 |
| keycloak | 统一门卫和临时通行证签发处 | 登录会话、客户端、基础角色、必要的用户映射 | 不会凭空知道业务系统里的项目关系 |
| 应用平台 | 真正提供功能的办公区 | 平台用户、项目成员关系、资源权限 | 不应自己保存或校验 ldap 密码 |
可以先把它们连成下面这张图:
登录链路
浏览器 ──> 应用平台 ──> keycloak ──> ldap
^ 验证令牌 <── 签发令牌 │
└──────────────── 登录成功 ────────────┘
授权链路
业务系统 ──同步部门、项目、角色──> 应用平台权限库
│
└──决定页面和接口能不能访问
注意,这里其实有两条独立链路:
- 登录链路:应用平台、keycloak 和 ldap 配合确认“小王是谁”。
- 授权链路:业务系统把项目和角色关系交给应用平台,应用平台判断“小王能做什么”。
只要把这两条链路分开,后面的配置就容易理解了。
第一步:小王入职,谁创建什么
管理员先在 ldap 中创建公司账号:
账号:xiaowang
姓名:王小明
邮箱:xiaowang@example.com
状态:在职
密码:只由身份目录安全保存和校验
业务管理员再在业务系统中安排工作:
员工:xiaowang
部门:示例部门
项目:示例项目
业务角色:项目管理员
这不是重复保存同一份数据,而是保存两类不同的事实:
ldap 的事实:xiaowang 是一个有效的公司账号
业务系统的事实:xiaowang 是示例项目的管理员
那么 keycloak 和应用平台里的用户从哪里来?常见做法有两种:
- 首次登录时创建:小王第一次登录成功后,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 签发的;
- 令牌是不是签给自己的;
- 令牌是否已经过期;
- 用户是否具备访问当前接口所需的基础角色。
所以,keycloak 不是把“登录成功”口头告诉应用平台,而是签发一个应用平台能够验证的令牌。实际通常使用 openid connect,它建立在 oauth 2.0 之上。
第三步:登录成功后,应用平台怎样知道小王能管理哪个项目
仅仅登录成功,只能证明当前用户是 xiaowang,不能证明他是“示例项目”的管理员。
应用平台还要查询自己的权限数据:
令牌告诉应用平台:当前用户是 xiaowang
↓
应用平台查询权限库:xiaowang 属于哪些项目?
↓
查询结果:示例项目,角色为管理员
↓
应用平台允许他进入示例项目的管理页面并调用管理接口
这里要特别注意:keycloak 不会自动读取业务系统的数据库,也不会自动理解“项目管理员”的业务含义。
业务系统中的关系必须通过双方明确设计的方式传给应用平台,例如:
业务系统发现小王被加入示例项目
↓
调用应用平台提供的成员同步接口
↓
应用平台保存:xiaowang + 示例项目 + 管理员
↓
小王访问项目时,应用平台查询这条关系并放行
也可以由应用平台定时读取业务系统提供的受控接口,或者由消息系统传递变更事件。无论用哪种方式,都应该有明确的字段映射、失败重试和审计记录,而不是让两个系统直接修改彼此的数据库。
为什么不把所有项目权限都放进 keycloak 令牌
把少量、稳定、多个应用都能理解的基础角色放进令牌通常比较合适,例如:
platform-user
platform-admin
auditor
但下面这类数据更适合由应用平台维护:
小王是项目 a 的管理员
小王是项目 b 的只读成员
小王只能操作项目 c 中的某几个资源
原因很直观:
- 项目越多,令牌越大;
- 项目权限经常变化,旧令牌中的内容不会自己改变;
- keycloak 只认识角色名称,不理解每个业务操作的具体规则;
- 最终保护数据和接口的是应用平台,它必须自己做最后一次权限检查。
因此,一个实用的分工是:
keycloak 令牌:用户身份 + 少量基础角色
应用平台权限库:项目、资源、成员关系等详细业务权限
这不是唯一方案,但很适合帮助初学者理解边界。
业务系统是否参与每次登录
在本文的示例架构中,不参与。
登录时的实时调用是:
应用平台 → keycloak → ldap
业务系统只在用户的部门、项目或角色发生变化时,把业务关系同步给应用平台。它不需要在每次登录时都在线。
如果某套系统把业务系统本身建设成了身份提供方,那么 keycloak 也可以把浏览器跳转到该系统登录。这是另一种架构:
应用平台 → keycloak → 业务身份提供方 → ldap
两种架构都可能成立,但不要混在一张流程图里。判断现场系统属于哪一种,只需查看 keycloak 配置的是“ldap 用户联合”,还是“外部身份提供方”。
管理员修改小王的角色后,什么时候生效
假设小王从“项目管理员”变成“普通成员”。完整变化过程是:
1. 管理员在业务系统修改小王的项目角色
2. 业务系统通过接口、事件或定时任务同步变更
3. 应用平台更新自己的项目成员关系
4. 小王再次调用项目接口
5. 应用平台读取最新权限,只允许普通成员的操作
如果变化的是 keycloak 令牌中的基础角色,还要考虑旧令牌:它在过期前仍可能带着旧角色。因此需要根据风险选择短令牌有效期、令牌刷新、会话撤销,或者让应用平台对高风险操作实时复核权限。
这也解释了为什么“后台已经改了角色,页面却没有立刻变化”:可能是同步任务还没执行,也可能是旧令牌或应用缓存还没失效。排查时应依次确认:
权威数据源是否已经修改
↓
同步是否成功
↓
应用平台权限库是否已经更新
↓
旧令牌或缓存是否仍在使用
小王离职后,又会发生什么
小王离职时,至少要处理两条链路:
身份链路:ldap 停用账号 → keycloak 不再签发新令牌
授权链路:业务系统移除关系 → 应用平台撤销项目和资源权限
仅仅停用 ldap 账号,并不代表已经签发的旧令牌会立即消失;仅仅删除应用平台的项目权限,也不代表账号不能登录。因此高风险系统还需要撤销 keycloak 会话、缩短令牌有效期,并确保应用平台每次访问都执行权限检查。
真正需要配置和开发哪些东西
把前面的原理落到实施工作上,通常分为三组。
keycloak 管理员配置
- 配置 ldap 地址、连接账号、用户搜索范围和字段映射;
- 配置应用平台客户端、回调地址和允许的登录流程;
- 决定哪些基础角色或用户字段进入令牌;
- 配置令牌有效期、会话和退出策略。
应用平台开发
- 接入
openid connect登录; - 验证 keycloak 令牌的签发方、接收方、签名和有效期;
- 用令牌中的稳定用户标识关联本地用户;
- 保存项目成员等详细权限,并在后端接口执行权限检查;
- 提供或调用受控的业务关系同步接口。
业务系统开发
- 明确哪些部门、项目和角色是权威数据;
- 在数据变化时调用接口、发送事件或等待定时同步;
- 记录同步结果,支持失败重试和审计;
- 只共享下游真正需要的数据。
keycloak 的配置只能完成统一身份和令牌能力。项目成员同步、业务角色解释、接口权限判断仍然需要业务系统和应用平台配合开发。
用三个问题判断一套设计是否清楚
面对真实系统时,可以直接问:
- 谁校验密码? 本文示例是 ldap。
- 谁签发应用平台信任的令牌? 本文示例是 keycloak。
- 谁对某个项目或资源的操作做最终决定? 本文示例是应用平台。
如果这三个问题没有明确答案,系统边界通常还没有设计清楚。
最后用一句话串起来
小王登录时,keycloak 请 ldap 验明身份并给他一张限时通行证;小王操作项目时,应用平台再根据业务系统同步来的项目关系,决定这张通行证能打开哪扇门。
所谓“用户管理集成”,不是把所有用户数据都复制到 keycloak,而是让身份、令牌和业务权限各有权威来源,再通过标准登录协议和受控同步接口把它们连起来。