问:之前OA系统中,User 和 Group 的映射关系,如何导入到 Keycloak 中呢?
这是一个非常关键的步骤。只有把这个映射关系导过去,你的用户在登录 Keycloak 后,Token 里才会带上正确的 Role,从而通过 Django 的权限验证。
这依然可以通过 Python 脚本来实现。逻辑分为三步:
-
找人: 根据 Django 的用户名,去 Keycloak 里找到对应的
User ID(Keycloak 内部是一个 UUID)。 -
找角色: 根据 Django 的 Group 名,去 Keycloak 里找到对应的
Role对象(需要包含 id 和 name 的完整字典)。 - 连线: 调用 Keycloak API,把这些 Roles 赋予给这个 User。
下面是一个完整的迁移脚本示例 migrate_mappings.py。
准备工作
确保你已经安装了库:
pip install python-keycloak django
迁移脚本 (migrate_mappings.py)
将此脚本放在 Django 项目根目录下运行:
import os
import django
from keycloak import KeycloakAdmin
# ---------------------------------------------------------
# 1. 初始化 Django 环境 (以便读取现有数据)
# ---------------------------------------------------------
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings') # 替换为你的项目名
django.setup()
from django.contrib.auth.models import User
# ---------------------------------------------------------
# 2. 连接 Keycloak Admin
# ---------------------------------------------------------
keycloak_admin = KeycloakAdmin(
server_url="http://localhost:8080/",
username='admin',
password='admin',
realm_name='my-company', # 你的 Realm 名称
user_realm_name='master',
verify=True,
)
def get_keycloak_user_id(username):
"""根据用户名查找 Keycloak 中的 User ID"""
users = keycloak_admin.get_users({"username": username})
if users:
return users[0]['id']
return None
def get_keycloak_role(role_name):
"""获取 Keycloak Role 的完整对象 (API 需要传对象,不仅仅是名字)"""
try:
return keycloak_admin.get_realm_role(role_name)
except Exception:
return None
# ---------------------------------------------------------
# 3. 开始迁移映射关系
# ---------------------------------------------------------
# 获取所有 Django 用户
django_users = User.objects.all()
print(f"🚀 开始迁移 {django_users.count()} 个用户的权限关系...")
success_count = 0
skip_count = 0
for django_user in django_users:
# A. 检查用户是否有组
user_groups = django_user.groups.all()
if not user_groups:
continue # 如果这个用户在 Django 里没组,跳过
print(f"\n正在处理用户: {django_user.username}")
# B. 在 Keycloak 里找到这个人
# 注意:这里假设两边用户名是一致的。如果不一致,需要你根据 email 匹配
kc_user_id = get_keycloak_user_id(django_user.username)
if not kc_user_id:
print(f"❌ Keycloak 中未找到用户 {django_user.username},跳过 (请先导入用户)")
skip_count += 1
continue
# C. 准备要赋予的角色列表
roles_to_assign = []
for group in user_groups:
role_obj = get_keycloak_role(group.name)
if role_obj:
roles_to_assign.append(role_obj)
else:
print(f"⚠️ 警告: Django 组 '{group.name}' 在 Keycloak 中找不到对应的 Role")
# D. 执行赋予操作 (批量赋予)
if roles_to_assign:
try:
keycloak_admin.assign_realm_roles(
user_id=kc_user_id,
roles=roles_to_assign
)
role_names = [r['name'] for r in roles_to_assign]
print(f"✅ 成功赋予角色: {role_names}")
success_count += 1
except Exception as e:
print(f"💥 赋予失败: {e}")
print(f"\n🎉 迁移完成! 成功处理: {success_count}, 跳过/失败: {skip_count}")
核心注意事项
为了确保脚本成功运行,请注意以下几点:
1. 用户必须先存在于 Keycloak
这个脚本只负责“建立关系”,不负责“创建用户”。
- 如果 Keycloak 里还是空的,你需要先写一个类似的脚本,把
auth_user表里的数据(username, email, first_name, last_name)导入到 Keycloak。 - 提示:Keycloak 不能导入 Django 的加密密码(哈希算法不同)。通常做法是导入用户后,重置密码或者配置“首次登录强制修改密码”。
2. 角色名必须匹配
脚本里是用 group.name 去找 Keycloak 的 Role。
- Django:
Manage Group - Keycloak:
Manage Group
如果名字对不上(比如大小写、空格),get_keycloak_role会找不到。
3. 性能优化 (如果有几万用户)
如果用户量非常大(>10,000),这个脚本可能会跑很久,因为它是一个个用户去查 API 的。
-
优化思路: 先一次性把 Keycloak 的所有 User 和所有 Role 拉取到内存里建立
Map(字典),然后在内存里匹配,最后只调用assign_realm_roles接口。对于几千个用户,上面的脚本足够快了。
4. 验证结果
跑完脚本后:
- 去 Keycloak 后台 -> Users -> 点击某个用户 -> Role Mapping 标签页。
- 你应该能看到对应的 Role 已经出现在列表中了。
这一步做完,你的 “Django OA + 视频 App + Keycloak SSO” 的骨架就彻底搭建完成了!