IdentityServer4:移除access_token的entity Claim并保留ClaimsPrincipal内该Claim的方法
解决IdentityServer4中Token体积与ClaimsPrincipal获取Claim的矛盾
核心思路
把"entity"声明从Access Token中剥离,仅通过**用户信息端点(UserInfo Endpoint)**返回,既减小Token体积,又能让客户端通过标准流程获取该声明,无需额外调用API。
具体实现(修改ProfileService)
修改GetProfileDataAsync方法,根据请求来源区分是否返回"entity"声明:
public async Task GetProfileDataAsync(IdentityServer4.Models.ProfileDataRequestContext context) { var user = await _userManager.GetUserAsync(context.Subject); var principal = await _claimsFactory.CreateAsync(user); // 获取用户所有声明 var allClaims = principal.Claims.Select(c => new System.Security.Claims.Claim(c.Type, c.Value)).ToList(); // 分离出entity声明 var entityClaims = allClaims.Where(x => x.Type == "entity").ToList(); // 基础声明(排除entity) var baseClaims = allClaims.Where(x => x.Type != "entity").ToList(); // 先添加基础声明到IssuedClaims context.IssuedClaims.AddRange(baseClaims); // 添加角色声明 var roleClaims = _roleService.GetRoleClaims(user); context.IssuedClaims.AddRange(roleClaims); // 判断是否是UserInfo端点的请求,如果是则添加entity声明 if (context.Callers.Contains("UserInfo")) { context.IssuedClaims.AddRange(entityClaims); } }
客户端获取"entity"声明的方式
客户端拿到Access Token后,向IdentityServer的/connect/userinfo端点发起GET请求,将Access Token放在Authorization头(格式为Bearer {token}),即可拿到包含"entity"的完整用户声明集合。客户端可将响应解析后注入ClaimsPrincipal,无需额外API调用。
补充说明
- 确保客户端配置中已包含
profilescope(UserInfo端点默认依赖该scope),也可以为"entity"声明单独创建自定义scope,客户端请求该scope即可获取对应声明。 - 该方案完全遵循OAuth2/OpenID Connect标准流程,不会引入额外复杂度。
内容的提问来源于stack exchange,提问作者user1884330
相关产品推荐
相关产品推荐

