从IdentityServer4迁移至WSO2 IS:Ocelot网关细粒度权限验证方案
背景概述
我正将身份认证提供商从IdentityServer4(.NET)迁移至WSO2 Identity Server。现有架构通过Ocelot API网关保护微服务,使用Skoruba Admin UI管理角色,并为角色动态分配细粒度权限声明;IdentityServer4会将这些权限扁平化到JWT的自定义permissions数组声明中,Ocelot网关期望的JWT Payload示例如下:
{ "sub": "test@gmail.com", "role": "manager", "permissions": [ "order.read", "order.write", "report.export" ] }
需在WSO2 IS中复刻该行为,同时通过WSO2 Console(UI)实现类似Skoruba的角色与权限管理,且无需重写代码即可适配现有Ocelot网关,现提出以下问题及对应解决方案:
问题1:传统权限扁平化方案实现
能否配置WSO2 IS,将用户角色关联的所有细粒度权限扁平化到JWT的单个自定义permissions数组声明中,与IdentityServer4/Skoruba的实现逻辑完全一致?
实现步骤
配置自定义声明
在WSO2 IS管理控制台中,进入Claims > Add,创建自定义声明:- Claim URI:
http://wso2.org/claims/permissions(可自定义) - Claim Display Name:
permissions - Supported by Default:勾选「是」
- Mapped Attribute:无需映射到用户存储属性,后续通过脚本填充
- Claim URI:
编写脚本填充权限数组
进入Identity Providers > Resident > Claim Configuration > Script Based Claim Filtering,启用脚本编辑,添加逻辑:// 获取用户所属所有角色 var roles = user.getRoleList(); var permissions = []; // 遍历角色读取关联权限(需提前在角色属性中配置逗号分隔的权限字符串) for each (var role in roles) { var rolePerms = role.getAttribute('permissions'); if (rolePerms) { permissions = permissions.concat(rolePerms.split(',')); } } // 去重处理 var uniquePerms = [...new Set(permissions)]; // 将权限数组注入JWT声明 executeStep(1, { 'permissions': uniquePerms });提前在Roles > 目标角色 > Attributes中添加
permissions属性,值为该角色的细粒度权限(如order.read,order.write)。配置JWT输出规则
进入Service Providers > 对应Ocelot网关服务 > Claim Configuration:- 在Requested Claims中添加自定义
permissions声明,设置为「Always Include in the Response」 - 在Local & Outbound Claim Configuration中,将该声明的Outbound Claim Name设为
permissions,确保JWT输出键名匹配要求
- 在Requested Claims中添加自定义
验证效果
发起授权请求后解析JWT,即可看到permissions数组包含所有角色关联的细粒度权限,与IdentityServer4输出格式完全一致。
问题2:基于WSO2 Scope体系的适配方案
若严格遵循WSO2 IS的角色-Scope映射机制,如何对接Ocelot这类外部网关?是否需要在登录流程中逐个请求细粒度Scope,或可通过“宏Scope”自动展开为细粒度权限?
实现步骤
配置宏Scope
WSO2 IS支持聚合多个细粒度Scope为一个宏Scope:- 进入Scopes > Add,创建细粒度Scope(如
order.read、order.write),每个Scope对应一个权限 - 创建宏Scope(如
manager-permissions),在Scope Associations中关联所有需要的细粒度Scope - 进入Roles > 目标角色 > Permissions > Scopes,为角色分配该宏Scope
- 进入Scopes > Add,创建细粒度Scope(如
对接Ocelot网关
在Ocelot配置中,将授权请求的scope参数设为宏Scope名称(如manager-permissions);WSO2 IS会自动将宏Scope展开为所有关联的细粒度Scope,并写入JWT的scope声明。
若Ocelot需要读取permissions数组而非scope,可通过声明转换实现:
进入Service Providers > 对应服务 > Local & Outbound Claim Configuration,添加新的Outbound Claim:- Local Claim URI:
http://wso2.org/claims/scope - Outbound Claim Name:
permissions - Transformation脚本:
function transform(claimValue) { return claimValue.split(' '); }
无需逐个请求细粒度Scope,仅需请求宏Scope即可获取所有关联权限。
- Local Claim URI:
WSO2 IS + 外部网关授权标准模式指导
角色-权限管理规范
- 优先使用WSO2 IS内置的角色-Scope体系,通过宏Scope简化授权请求;若需完全兼容现有Ocelot的
permissions格式,采用自定义脚本填充声明的方案 - 通过WSO2 Console的Roles界面统一管理角色权限关联,无论是自定义属性存储的权限列表还是分配的Scope,均可在同一界面操作,实现类Skoruba的管理体验
- 优先使用WSO2 IS内置的角色-Scope体系,通过宏Scope简化授权请求;若需完全兼容现有Ocelot的
网关对接模式选择
- JWT验证模式:外部网关直接验证WSO2 IS签发的JWT,读取声明中的权限信息做路由控制;此模式无需网关与WSO2 IS实时通信,性能更高
- Introspection模式:网关将JWT发送至WSO2 IS的Introspection端点,验证令牌有效性并获取权限信息;此模式支持实时令牌状态检查,适合高安全要求场景
声明标准化建议
- 跨系统兼容场景优先使用标准OIDC声明;自定义声明需提前规划URI与名称,避免冲突
- 通过WSO2 IS的Claim Dialects统一管理自定义声明的映射与输出格式
内容的提问来源于stack exchange,提问作者Movses Aleksanyan

