为什么Asp.net core Identity流程中UserClaims未被添加到授权Cookie中
问题根因
ASP.NET Core Identity + 模板自带的IdentityServer4默认不会自动将AspNetUserClaims表中的自定义声明(包括角色声明)写入签发的Cookie/访问令牌,仅默认携带用户ID、用户名等基础声明,需要手动配置声明加载和下发规则。
解决步骤
- 自定义用户声明工厂,加载数据库中的所有自定义声明
创建自定义声明工厂类,替换Identity默认的声明生成逻辑:
public class CustomUserClaimsPrincipalFactory : UserClaimsPrincipalFactory<IdentityUser> { public CustomUserClaimsPrincipalFactory(UserManager<IdentityUser> userManager, IOptions<IdentityOptions> optionsAccessor) : base(userManager, optionsAccessor) { } protected override async Task<ClaimsIdentity> GenerateClaimsAsync(IdentityUser user) { var identity = await base.GenerateClaimsAsync(user); // 从数据库加载当前用户的所有声明加入身份凭证 var userClaims = await UserManager.GetClaimsAsync(user); identity.AddClaims(userClaims); return identity; } }
在Startup.cs的ConfigureServices方法中注册该工厂:
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores<ApplicationDbContext>() // 注册自定义声明工厂 .AddClaimsPrincipalFactory<CustomUserClaimsPrincipalFactory>();
- 配置IdentityServer下发角色声明
.NET 5的ASP.NET Core + Angular + 个人账号模板默认集成了IdentityServer4,需要额外配置允许向令牌中写入角色声明:
services.AddIdentityServer() .AddApiAuthorization<IdentityUser, ApplicationDbContext>(options => { // 身份令牌携带角色声明 options.IdentityResources["openid"].UserClaims.Add("role"); // 访问令牌携带角色声明,供API校验权限使用 options.ApiResources.Single().UserClaims.Add("role"); }); // 移除JWT默认的声明类型映射,避免角色声明名称被自动改写导致匹配失败 JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("role");
- 验证规则生效
修改完配置后重新编译项目,手动清空浏览器旧的Cookie和本地存储的令牌,重新登录后即可在Cookie/访问令牌中看到新增的角色声明,[Authorize(Roles = "IAmTheWallrus")]校验即可正常生效。
如果你的数据库中存储的角色声明类型是完整的Schema地址http://schemas.microsoft.com/ws/2008/06/identity/claims/role,将上面配置中的"role"替换为完整的声明地址即可。
内容的提问来源于stack exchange,提问作者gakera
相关产品推荐
相关产品推荐

