.NET 8升级后ASP.NET Core Web API出现HTTP 403权限错误
.NET 8迁移后JWT角色验证导致403错误排查
维护的ASP.NET Core Web API项目采用Duende Identity Server、JWT Bearer令牌及基于角色的端点访问控制,升级至.NET 8(Microsoft.AspNetCore.App框架版本8.0.7)后出现HTTP 403错误。
项目中builder.ConfigureServices()的身份验证配置如下:
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); builder.Services .AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer("Bearer", options => { options.Authority = "id.YouDontNeedToKnow.example.com"; options.TokenValidationParameters = new TokenValidationParameters { ValidateAudience = false, NameClaimType = "sub", RoleClaimType = "role", ValidTypes = [ "at+jwt" ] }; }); builder.Services .AddAuthorization(options => { options.AddPolicy("Admin", AuthorisationPolicies.Admin()); });
通过Swagger追踪端点请求,得到验证失败提示:
RolesAuthorizationRequirement:User.IsInRole must be true for one of the following roles: (Admin)
问题根源
User.IsInRole("Admin")验证不通过,说明JWT令牌中的角色声明未被ASP.NET Core正确识别为用户角色。核心原因是:
- .NET中
IsInRole方法默认检查**ClaimTypes.Role类型**的声明(对应URI:http://schemas.microsoft.com/ws/2008/06/identity/claims/role) - 当前配置中
RoleClaimType = "role",仅将JWT里的role声明标记为角色类型,但未映射到.NET默认的角色Claim类型,导致授权逻辑无法识别。
解决方案
方案1:调整TokenValidationParameters映射
将RoleClaimType设置为.NET默认的ClaimTypes.Role,让JwtBearer自动将JWT中的role声明转换为.NET可识别的角色类型:
options.TokenValidationParameters = new TokenValidationParameters { ValidateAudience = false, NameClaimType = ClaimTypes.NameIdentifier, // 可选:将sub映射为标准NameIdentifier RoleClaimType = ClaimTypes.Role, ValidTypes = [ "at+jwt" ] };
方案2:修改授权策略匹配自定义声明
如果不想调整Claim类型映射,直接修改Admin策略,校验JWT中的role声明:
// 假设AuthorisationPolicies.Admin()的实现改为: public static AuthorizationPolicy Admin() { return new AuthorizationPolicyBuilder() .RequireClaim("role", "Admin") .Build(); }
方案3:手动转换角色声明(事件处理)
在JwtBearer配置中添加OnTokenValidated事件,手动将role声明转换为ClaimTypes.Role类型:
.AddJwtBearer("Bearer", options => { options.Authority = "id.YouDontNeedToKnow.example.com"; options.TokenValidationParameters = new TokenValidationParameters { ValidateAudience = false, NameClaimType = "sub", RoleClaimType = "role", ValidTypes = [ "at+jwt" ] }; options.Events = new JwtBearerEvents { OnTokenValidated = context => { var identity = context.Principal.Identity as ClaimsIdentity; if (identity != null) { // 提取所有role声明并转换为标准角色类型 var roleClaims = identity.FindAll("role"); foreach (var claim in roleClaims) { identity.AddClaim(new Claim(ClaimTypes.Role, claim.Value)); } } return Task.CompletedTask; } }; });
额外检查项
- 解码请求令牌,确认
role声明存在且值为Admin - 确认Duende Identity Server客户端配置中已正确授予
Admin角色权限 - 确保Program.cs中中间件顺序正确:
app.UseAuthentication()必须在app.UseAuthorization()之前
内容的提问来源于stack exchange,提问作者Logopolitan
相关产品推荐
相关产品推荐

