如何在Keycloak最新版本中按用户角色将关联资源存入令牌
在Keycloak最新版本中自动将角色关联资源存入令牌Payload的实现方法
前提确认
确保你的目标客户端已开启Authorization Services:进入客户端的Settings标签页,勾选Authorization Enabled并保存。
核心方案:自定义脚本映射器
通过编写脚本映射器,动态遍历用户的所有角色,关联对应的资源并写入令牌Payload:
创建脚本映射器
- 进入目标客户端的
Mappers标签页,点击Create。 - 选择
Script Mapper类型,填写基础信息:- 名称:比如
角色关联资源映射 - Token Claim Name:自定义Payload字段名,比如
allowed_resources - Claim JSON Type:选择
Array(用于存储资源列表)
- 名称:比如
- 在
Script框中填入以下Groovy脚本(可根据你的资源-策略关联逻辑调整):import org.keycloak.models.ResourceModel import org.keycloak.models.RoleModel import org.keycloak.services.resource.authorization.AuthorizationProvider def authProvider = session.getProvider(AuthorizationProvider.class) def client = authProvider.getStoreFactory().getClientStore().findById(clientId) def resourceList = [] // 收集用户的所有角色(Realm角色 + 客户端角色) def allRoles = [] allRoles.addAll(user.getRealmRoleMappings()) allRoles.addAll(user.getClientRoleMappings(client)) // 遍历角色,关联对应的资源 for (RoleModel role : allRoles) { // 查询该角色绑定的所有策略 def policies = authProvider.getStoreFactory().getPolicyStore().findByRole(role) for (policy in policies) { // 查询策略关联的权限 def permissions = authProvider.getStoreFactory().getPermissionStore().findByPolicy(policy) for (permission in permissions) { // 获取权限对应的资源 ResourceModel resource = authProvider.getStoreFactory().getResourceStore().findById(permission.getResourceId()) if (resource && !resourceList.contains(resource.getName())) { resourceList.add(resource.getName()) } } } } // 返回去重后的资源列表 return resourceList.unique() - 保存映射器。
- 进入目标客户端的
验证效果
通过授权码/密码模式获取用户的访问令牌,解码后查看Payload中是否存在你定义的字段(比如allowed_resources),其中包含该用户角色关联的所有资源名称。
替代方案:使用权限令牌
如果不需要将资源直接写入JWT Payload,而是需要更细粒度的权限信息:
- 进入客户端的
Authorization标签页,打开Token Settings,勾选Issue Permission Token。 - 获取令牌时会附带权限令牌,其中包含用户可访问的所有资源、权限等详细信息,适合需要动态校验权限的场景。
注意事项
- 脚本逻辑需匹配你的实际配置:如果策略不是基于角色绑定的(比如基于用户属性),需要调整脚本中的策略查询逻辑。
- 确保脚本拥有足够权限:Keycloak默认允许脚本访问授权相关API,若遇权限问题可在
Server Info->Providers中检查脚本引擎配置。
内容的提问来源于stack exchange,提问作者Gaurav Jaiswal
相关产品推荐
相关产品推荐

