为.NET Identity添加JWT后基于角色的授权失效问题
解决方案:.NET Identity与JWT共存时角色授权失败问题
问题根源
当你将JWT设为默认认证Scheme时,[Authorize(Roles = "Admin")]会默认使用JWT Scheme进行认证,忽略了Identity的Cookie认证。同时,若Identity生成的ClaimsPrincipal中缺少ClaimTypes.Role类型的角色声明,也会导致角色校验失败。
具体解决步骤
1. 确保Identity用户的角色声明正确注入
自定义AppClaimsPrincipalFactory,确保用户的角色被添加为标准的ClaimTypes.Role声明:
public class AppClaimsPrincipalFactory : UserClaimsPrincipalFactory<IdentityUser, IdentityRole> { private readonly UserManager<IdentityUser> _userManager; public AppClaimsPrincipalFactory(UserManager<IdentityUser> userManager, RoleManager<IdentityRole> roleManager, IOptions<IdentityOptions> optionsAccessor) : base(userManager, roleManager, optionsAccessor) { _userManager = userManager; } protected override async Task<ClaimsIdentity> GenerateClaimsAsync(IdentityUser user) { var identity = await base.GenerateClaimsAsync(user); // 获取用户角色并添加为标准Role声明 var roles = await _userManager.GetRolesAsync(user); foreach (var role in roles) { identity.AddClaim(new Claim(ClaimTypes.Role, role)); } return identity; } }
2. 调整授权策略(二选一即可)
方案A:直接在控制器中指定多认证Scheme
修改WeatherForecastController的Authorize属性,明确允许JWT和Identity Cookie两种认证方式:
[HttpGet, Authorize(AuthenticationSchemes = "Identity.Application,JwtBearer", Roles = "Admin")] public IEnumerable<WeatherForecast> Get() { // 方法逻辑不变 }
方案B:创建全局自定义授权策略
在启动类的授权配置中添加支持双Scheme的Admin专属策略:
builder.Services.AddAuthorization(options => { options.DefaultPolicy = new AuthorizationPolicyBuilder("Identity.Application", JwtBearerDefaults.AuthenticationScheme) .RequireAuthenticatedUser() .Build(); // 添加Admin角色专属策略,支持两种认证方式 options.AddPolicy("AdminAccess", policy => { policy.AddAuthenticationSchemes("Identity.Application", JwtBearerDefaults.AuthenticationScheme); policy.RequireAuthenticatedUser(); policy.RequireRole("Admin"); }); });
然后在控制器中使用该策略:
[HttpGet, Authorize(Policy = "AdminAccess")] public IEnumerable<WeatherForecast> Get() { // 方法逻辑不变 }
3. 验证用户角色分配
确保测试用户确实被分配了Admin角色,可以通过以下代码确认:
// 在注册或用户管理逻辑中添加角色分配 var user = await _userManager.FindByNameAsync("你的测试用户名"); await _userManager.AddToRoleAsync(user, "Admin");
内容的提问来源于stack exchange,提问作者AJ Raj
相关产品推荐
相关产品推荐

