Keycloak 为什么需要自定义协议 Mapper?

Keycloak 中,自定义协议 Mapper(Custom Protocol Mapper) 是一种非常强大的机制,它允许你 动态地将用户属性、客户端属性或其他信息注入到 Token(ID Token 或 Access Token)中


🧠 为什么需要自定义协议 Mapper?

Keycloak 默认的(访问) Token 只包含一些基础字段,如 subpreferred_usernameemail 等。但在实际业务中,我们往往希望:

  • 把用户的 租户 ID(tenant_id)
  • 用户所属的 组织名称(organization_name)
  • 用户的角色权限(roles
  • 客户端相关的元数据(client_metadata
  • 自定义业务字段(如部门、职位、区域等)

通过 自定义协议 Mapper,你可以灵活控制(访问) Token 的内容,满足后端服务 鉴权、路由、多租户管理 等需求。


✅ 场景举例

场景描述
多租户系统将用户的 tenant_id 注入 Token,便于下游服务识别归属租户
微服务认证在 Token 中添加 department, location, role_level 等字段用于访问控制
第三方集成向特定 client 发放 token 时添加 integration_keyapi_key
动态权限根据用户角色或属性生成 permissions 字段

🔧 配置步骤:如何创建一个自定义协议 Mapper

以下以向 Token 添加 tenant_id 字段为例,介绍如何配置一个自定义协议 Mapper

步骤 1:进入 Client Scopes 页面

  1. 登录 Keycloak 管理后台
  2. 进入对应 Realm
  3. 左侧菜单点击 Client Scopes
  4. 选择你要绑定 MapperScope(通常为 profileyour_clientdefault scope

步骤 2:添加新的 Mapper

  1. 点击页面上的 Add mapper > By configuration
  2. 选择 Mapper 类型:
    • 推荐使用 User Attribute Mapper(将用户属性注入 Token

步骤 3:填写 Mapper 表单(以 User Attribute 为例)

字段说明
Nametenant_idMapper 名称(任意命名)
Mapper TypeUser Attribute表示从用户属性中提取数据
User Attributetenant_id用户实体中的属性名(需提前设置好)
Token Claim Nametenant_id最终在 Token 中的字段名
Claim Value TypeString / JSON / Long数据类型
Add to ID token✅ Yes是否写入 ID Token
Add to access token✅ Yes是否写入 Access Token
Friendly Name可选显示用名称
Description可选描述

✅ 保存后,该字段将在后续签发的 Token 中自动出现。


📦 示例:Token 输出效果

  • 假设某用户有如下属性:
{
  "username": "john_doe",
  "attributes": {
    "tenant_id": "tenant_001",
    "department": "IT"
  }
}
  • 配置好 Mapper 后,获取的 Token 将包含:
{
  "exp": 1718000000,
  "iat": 1718000000,
  "jti": "abc123...",
  "iss": "https://keycloak.example.com/auth/realms/myrealm",
  "aud": "my-client",
  "sub": "user-uuid",
  "tenant_id": "tenant_001",   ← 新增字段
  "department": "IT"           ← 可选新增字段
}

🧩 其他常见 Mapper 类型(可选)

除了 User Attribute,还有多种类型的 Mapper 可供使用:

Mapper 类型用途说明
User Attribute从用户属性映射字段
Role Name显示当前用户的所有角色
Group Membership显示用户所属组(group)
Hardcoded claim固定值字段(如 environment=production)
Script Mapper使用 JavaScript 脚本动态构造字段(高级)
Audience添加 audience 字段
Attribute StatementSAML 协议相关

如果你需要更复杂的逻辑(比如根据用户角色动态生成权限列表),可以使用 Script Mapper


🧪 Script Mapper 示例(高级用法)

场景:根据用户角色生成权限字段 permissions

1. 创建 Script Mapper
  • Mapper TypeScript Mapper
  • Namepermissions-mapper
  • Script
// 获取用户所有角色
var roles = user.getRealmRoleMappings();
var permissions = [];

if (roles) {
    for (var i = 0; i < roles.size(); i++) {
        var role = roles.get(i);
        if (role.getName().startsWith("perm_")) {
            permissions.push(role.getName().replace("perm_", ""));
        }
    }
}

$token.setOtherClaims("permissions", permissions);
2. 效果(Token 中新增字段)
{
  "permissions": ["read:data", "write:data", "delete:user"]
}

🧰 如何给 Service Account 用户添加属性(client_credentials 模式)

如果你使用的是 client_credentials 模式,你需要给 Service Account 用户 添加属性:

步骤:

  1. 打开你的 Client 设置页
  2. 点击 Service Account Settings
  3. 开启 Service Account Enabled
  4. 查看 Service Account 用户(通常是 service-account-{client-id}
  5. 编辑该用户,在 Attributes 中添加 tenant_id: tenant_001
  6. 再次请求 Token,你应该能在 Token 中看到这个字段

🧩 Mapper 的作用范围

Mapper 可以绑定到不同作用域:

作用域说明
Realm-Level Mappers对整个 Realm 下的所有 Token 生效
Client-Level Mappers仅对该 Client 签发的 Token 生效
Client Scope Mappers绑定到某个 Scope,只有请求该 Scope 时才生效

例如:

  • 你想让所有 Client 都带上 tenant_id → 放到 Realm-Level Mapper
  • 你只想让特定 Client 带上 tenant_id → 放到 Client-Level Mapper
  • 你只想在某些 Scope 下带 tenant_id → 放到 Client Scope Mapper

🛠 常见问题排查

问题解决方法
Token 中没有新字段检查是否已启用 Mapper 并正确绑定 Scope
用户属性为空确保用户确实设置了该属性
Service Account 没有属性确认是 Service Account 用户本身设置了属性
Mapper 不生效清除缓存并重新获取 Token
Mapper 写入了错误位置检查是否勾选了 “Add to ID Token”“Add to Access Token”

✅ 总结

Mapper 类型适用场景是否推荐
User Attribute将用户属性注入 Token✅ 推荐
Role Name显示用户角色✅ 推荐
Group Membership显示用户所属组✅ 推荐
Hardcoded Claim固定字段✅ 快速调试
Script Mapper动态生成字段(如权限)✅ 高级用法
Audience添加目标受众✅ 安全增强

如果你能提供以下信息,我可以为你写出完整的配置指南:

  • Realm 名称
  • Client ID
  • 想要添加的字段名(如 tenant_idorg_code 等)
  • 你是想从 user 用户属性还是客户端属性取值
  • 是否使用 client_credentials 模式

欢迎继续提问,我将为你定制完整的配置方案!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ChaITSimpleLove

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值