使用client_credentials流时如何区分客户端配置数据访问权限
IdentityServer 客户端凭证流精细化数据权限实现方案
client_credentials流本身就是为M2M(机器对机器)通信场景设计的,你提到的按客户端维度绑定数据可见范围的需求属于该场景下的常规需求,官方提供了完整的标准扩展点,不需要挪用Description这类字段取巧实现。
具体实现按以下步骤走即可:
- 优先使用官方Client实体预留的自定义属性存储扩展数据
官方Client模型自带Properties字典属性,设计目的就是给业务方存储自定义关联配置,完全不需要额外找Id字段或者挪用其他语义字段。配置客户端时直接往这个字典里塞业务关联键、权限范围配置即可,示例配置如下:
额外提一句:// 客户端p的配置示例 new Client { ClientId = "client_p", AllowedGrantTypes = GrantTypes.ClientCredentials, ClientSecrets = { new Secret("p_client_secret".Sha256()) }, // 官方预留的自定义扩展属性存储位 Properties = { // 存你自有业务系统中第三方客户端表的主键,做关联用 { "BizClientFk", "你的第三方业务表中客户端p对应的主键值" }, // 业务量小的话也可以直接把允许访问的用户ID存在这里 { "AllowedUserList", "u" } } }ClientId本身就是Client实体的全局唯一逻辑主键,配置后不会随意变更,你完全可以直接把ClientId作为自有业务权限表的外键做关联,不需要额外找数字类型的Id字段,稳定性完全满足业务要求。 - 选择官方推荐的扩展点注入令牌声明
不需要自己额外做上下文匹配查询,两个官方预留的扩展点都可以实现声明注入:- 如果你需要在令牌请求阶段做额外校验,就实现
ICustomTokenRequestValidator接口,验证上下文参数里直接包含当前请求的完整Client对象,直接从context.Client.Properties或者通过ClientId查你自己的权限表,拿到当前客户端允许访问的用户范围,把对应的allowed_user_id类声明加到请求验证结果里即可。 - 如果只需要给令牌加自定义声明,不需要额外校验逻辑,直接实现
IClaimsProfileService(针对客户端凭证流要记得处理ClientClaimsContext场景,不要只处理用户场景),在生成令牌的环节把权限范围声明注入进去即可,实现更轻量。
- 如果你需要在令牌请求阶段做额外校验,就实现
- API侧做数据范围过滤
接口拿到请求后,直接从当前用户令牌的声明中提取当前客户端允许访问的用户ID集合,查询数据时追加过滤条件即可,示例逻辑:// 提取当前M2M客户端可访问的用户ID集合 var allowedUsers = User.Claims .Where(c => c.Type == "allowed_user_id") .Select(c => c.Value) .ToHashSet(); // 查询数据时追加范围过滤,只返回授权范围内的数据 var result = await _dbContext.UserBusinessData .Where(data => allowedUsers.Contains(data.UserId)) .ToListAsync();
注意不要为了这个需求直接修改IdentityServer的官方模型定义或者底层表结构,后续版本升级、数据迁移会有很高的维护成本。如果后续客户端规模扩大、权限规则变复杂,直接把客户端-用户授权关系存在你自有的权限表中,用ClientId做关联键即可,是官方推荐的标准做法。
内容的提问来源于stack exchange,提问作者Richard Barraclough
相关产品推荐
相关产品推荐

