ASP.NET Core中带[Authorize(Roles)]的接口调用出现403权限错误
JWT角色授权403错误排查与修复
问题描述
实现简单JWT令牌授权后,无角色限制的接口可正常调用,但给方法添加特定角色访问限制后,调用出现403权限错误。已通过RoleService在数据库中注册角色,但问题仍未解决。
核心错误点及修复方案
1. Token生成时角色Claim构造错误
在JWTService.GenerateToken方法中,Claim的参数传递逻辑错误,导致角色信息未被正确写入Token:
原错误代码:
var claims = new List<Claim> { new Claim(ClaimsIdentity.DefaultNameClaimType, name, ClaimsIdentity.DefaultRoleClaimType, role) };
这里错误地将角色Claim类型作为Issuer参数传递,正确做法是单独添加角色Claim:
修正后代码:
public string GenerateToken(string name, string role) { var claims = new List<Claim> { new Claim(ClaimsIdentity.DefaultNameClaimType, name), new Claim(ClaimsIdentity.DefaultRoleClaimType, role) // 单独添加角色类型的Claim }; var jwt = new JwtSecurityToken( issuer: AuthOptions.ISSUER, audience: AuthOptions.AUDIENCE, claims: claims, expires: DateTime.Now.AddSeconds(20), signingCredentials: new SigningCredentials(AuthOptions.GetSymmetricSecurityKey(), SecurityAlgorithms.HmacSha256) ); return new JwtSecurityTokenHandler().WriteToken(jwt); }
2. 角色名称与授权规则不匹配
- 控制器中使用
[Authorize(Roles = "admin")],但RoleService中创建的角色是"administrator"、"cook"、"waiter",角色名称完全不匹配,直接导致403。 - Program.cs中的授权策略逻辑错误,原代码要求存在名为
"admin"的Claim,而非校验角色:
原错误策略:
option.AddPolicy("admin", policyBuilder => policyBuilder.RequireClaim("admin", "waiter", "cook"));
修正后授权策略:
builder.Services.AddAuthorization(option => { // 仅允许管理员访问的策略 option.AddPolicy("AdministratorOnly", policyBuilder => policyBuilder.RequireRole("administrator")); // 允许管理员/服务员/厨师访问的策略 option.AddPolicy("StaffAccess", policyBuilder => policyBuilder.RequireRole("administrator", "waiter", "cook")); });
修正后控制器注解:
[HttpGet] [Authorize(Policy = "AdministratorOnly")] // 或直接用[Authorize(Roles = "administrator")] [Route("getSecretInfo")] public IActionResult GetSecretInfo() { return Ok("QWERTY"); }
3. 中间件顺序错误
Program.cs中UseAuthorization和UseCors顺序颠倒,CORS需要在授权前处理跨域请求:
原错误顺序:
app.UseAuthorization(); app.UseCors(Origins);
修正后顺序:
app.UseCors(Origins); app.UseAuthorization();
4. Identity DbContext冗余配置
RestarauntTPDBIdentityDBContext继承IdentityDbContext<IdentityUser>后,无需额外定义DbSet<IdentityRole>,且OnConfiguring方法可删除(已在Program.cs中配置连接字符串):
修正后DbContext:
public class RestarauntTPDBIdentityDBContext : IdentityDbContext<IdentityUser> { public RestarauntTPDBIdentityDBContext(DbContextOptions<RestarauntTPDBIdentityDBContext> options) : base(options) { } }
验证步骤
- 生成Token后,通过JWT解析工具确认Token中包含正确的角色Claim(如
"role": "administrator")。 - 确认登录时传递给
GenerateToken的role参数与数据库中角色名称一致。 - 检查数据库中用户是否已被正确分配对应角色(若使用Identity用户角色关联)。
内容的提问来源于stack exchange,提问作者user23893421
相关产品推荐
相关产品推荐

