引入 Keycloak 的准备

问:之前OA系统中,User 和 Group 的映射关系,如何导入到 Keycloak 中呢?

这是一个非常关键的步骤。只有把这个映射关系导过去,你的用户在登录 Keycloak 后,Token 里才会带上正确的 Role,从而通过 Django 的权限验证。

这依然可以通过 Python 脚本来实现。逻辑分为三步:

  1. 找人: 根据 Django 的用户名,去 Keycloak 里找到对应的 User ID(Keycloak 内部是一个 UUID)。
  2. 找角色: 根据 Django 的 Group 名,去 Keycloak 里找到对应的 Role 对象(需要包含 id 和 name 的完整字典)。
  3. 连线: 调用 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. 验证结果
跑完脚本后:

  1. 去 Keycloak 后台 -> Users -> 点击某个用户 -> Role Mapping 标签页。
  2. 你应该能看到对应的 Role 已经出现在列表中了。

这一步做完,你的 “Django OA + 视频 App + Keycloak SSO” 的骨架就彻底搭建完成了!

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • """1.个性化消息: 将用户的姓名存到一个变量中,并向该用户显示一条消息。显示的消息应非常简单,如“Hello ...
    她即我命阅读 9,195评论 0 6
  • 1、expected an indented block 冒号后面是要写上一定的内容的(新手容易遗忘这一点); 缩...
    庵下桃花仙阅读 3,868评论 0 2
  • 一、工具箱(多种工具共用一个快捷键的可同时按【Shift】加此快捷键选取)矩形、椭圆选框工具 【M】移动工具 【V...
    墨雅丫阅读 4,429评论 0 0
  • 跟随樊老师和伙伴们一起学习心理知识提升自已,已经有三个月有余了,这一段时间因为天气的原因休课,顺便整理一下之前学习...
    学习思考行动阅读 3,725评论 0 2
  • 一脸愤怒的她躺在了床上,好几次甩开了他抱过来的双手,到最后还坚决的翻了个身,只留给他一个冷漠的背影。 多次尝试抱她...
    海边的蓝兔子阅读 3,362评论 0 4

友情链接更多精彩内容