假设我们要给一家上千人的企业升级 OA 系统,除了传统的打卡审批,还要接入当下最火的 AI 大模型辅助办公。这时候,整个公司的技术架构就不再是只有 Django 这一根“独苗”了,而是会变成“Django 写的 OA 后端” + “专门跑 AI 的独立服务” + “各种第三方内部工具”。
如果继续用 Django 自带的 auth 系统,不仅几千人的账号密码同步会让人崩溃,而且体验极差——员工在 OA 签完到,切到 AI 助手页面时,还得再登录一次。
这就是我们要引入 Keycloak 的原因:把“管账号”这件事,从具体的业务系统里剥离出来,交给专业的“安保中心”去做。
一、 一秒看懂 Keycloak 的“安保体系”
用现实中的“企业园区门禁系统”来类比,Keycloak 里的那些名词就非常直白了:
- Realm (租户空间): 相当于“整个数字企业园区”。你所有的系统(OA、AI、网盘)、所有的几千名员工,都在这个大园区里统一管理。
- Client (客户端): 相当于园区里的“具体业务大楼”。你的 Django OA 系统是一栋楼,AI 服务中心是另一栋楼。
- Realm Roles (全局角色): 相当于员工胸牌上的“全局职位标签”。比如“高管”、“普通员工”。不管这名员工走进园区里的哪栋大楼,大家都认这个标签。
- Client Roles (应用私有角色): 相当于某栋大楼里的“特定房间钥匙”。比如在 Django OA 这栋楼里,有个角色叫“请假审批人”。这个头衔只在 OA 楼里好使,要是他去了 AI 楼,这个“请假审批人”的头衔毫无意义。这就是为什么不能全用全局角色的原因。
二、 拆解 JWT 日志:这就是一张“电子通行证”
员工在统一登录页输入密码后,Keycloak 会发给他一张不可伪造的“电子通行证”(也就是你日志里抓取到的那串 JWT JSON)。员工拿着这张证去敲 Django OA 的大门,Django 只需要看懂这张证就行了。
用大白话翻译Django的日志(Claims):
{
// 【谁发的证?】
// Keycloak 安保中心发的,证明这是咱们园区的合法员工。
"iss": "http://localhost:8080/realms/sigma-realm",
// 【这证能在哪栋楼用?】
// 明确写了只能在 django-admin-client (OA大楼) 用。
// 如果员工拿错证,Django 直接拒之门外。
"aud": "django-admin-client",
// 【这是谁?】
// 员工的全球唯一数字工号 (UUID)。这比名字靠谱,重名也不怕。
"sub": "a520d9a2-e3cd-4915-ad6e-70522e4773db",
// 【他有什么全局特权?】
// 哟,这人身上带有 admin(超级管理员)的全局标签,是个大人物。
"realm_access": ["default-roles-sigma-realm", "offline_access", "admin"],
// 【基本档案】
// 姓名和工作邮箱。Django 拿到后可以直接在右上角显示 "欢迎, Test Admin"。
"name": "Test Admin",
"email": "testadmin@example.com"
}
三、 踩坑后总结的业界最佳实践
在千人规模的企业实施这套系统时,以下几个最佳实践能帮你省去 80% 的后期维护痛苦:
1. 坚决执行“基于用户组(Group)”的权限分配原则
-
错误做法: 在后台把
OA_管理员这个角色直接分配给员工张三。 -
最佳实践: 建立一个叫
研发部_IT支持的 Group(部门群组)。把OA_管理员的权限赋给这个 Group,然后再把张三拉进这个 Group。未来张三转岗或离职,只需要把他从 Group 踢出去,他的所有权限瞬间自动回收,干净利落。
2. 抛弃 Django 自增 ID,拥抱 UUID
由于现在账号是 Keycloak 管的,Django 里的 User 表不再是唯一的主宰。
-
最佳实践: 在 Django 重写 User 模型时,把主键(或者核心关联键)设为 JWT 里传过来的那个
sub(UUID)。这样以后不管是 OA 库、AI 数据库还是财务数据库,只要看到这个 UUID,就知道是同一个人,数据打通毫无障碍。
3. 把所有登录相关的破事全丢给 Keycloak
- 最佳实践: 让 Django 彻底变成一个“无状态”的 API 服务。不要在 Django 里写找回密码、修改密码、手机号验证码登录的代码。这些 Keycloak 自带的开箱即用功能比我们手写的安全得多。Django 只需要专心处理业务逻辑(比如审批流程怎么走、AI 模型怎么调用)即可。