You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core中JWT角色授权返回401 Unauthorized问题求助

ASP.NET Core JWT角色授权返回401 Unauthorized排查

我正在使用ASP.NET Core开发基于JWT的认证与角色授权系统,用户登录时生成包含Role声明的JWT令牌,但请求带有[Authorize(Roles = "User")]特性的接口时,持续收到“401 Unauthorized”错误,请求协助排查。

相关代码

登录方法

public IDataResult<string> Login(UserForLoginDto userForLoginDto)
{
    var userToCheck = _userService.GetByMail(userForLoginDto.Email).Data;

    if (userToCheck == null)
    {
        return new ErrorDataResult<string>("User not found");
    }

    if (userToCheck.Password != userForLoginDto.Password)
    {
        return new DataResult<string>(null, false, "Invalid email or password");
    }

    var userClaims = _userDal.GetClaims(userToCheck);
    var token = _tokenHelper.GenerateToken(userToCheck, userClaims);

    return new DataResult<string>(token, true, "Login successful");
}

令牌生成方法

public string GenerateToken(User user, List<OperationClaim> operationClaims)
{
    var claims = new List<Claim> { new Claim(ClaimTypes.Name, user.Email) };

    foreach (var operationClaim in operationClaims)
    {
        claims.Add(new Claim(ClaimTypes.Role, operationClaim.Name));
    }

    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["TokenOptions:SecurityKey"]));
    var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

    var token = new JwtSecurityToken(
        issuer: _configuration["TokenOptions:Issuer"],
        audience: _configuration["TokenOptions:Audience"],
        claims: claims,
        expires: DateTime.Now.AddDays(3),
        signingCredentials: creds);

    return new JwtSecurityTokenHandler().WriteToken(token);
}

受保护接口

[HttpGet("GetAll")]
[Authorize(Roles = "User")]
public IActionResult GetAll()
{
    var cars = _carService.GetAll();

    if (cars.Success)
        return Ok(cars);

    return BadRequest(cars);
}

认证配置

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = configuration["TokenOptions:Issuer"],
            ValidAudience = configuration["TokenOptions:Audience"],
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["TokenOptions:SecurityKey"]))
        };
    });

app.UseAuthentication();
app.UseAuthorization();

请求截图

请求截图

排查与解决建议

  • 校验令牌内的Role声明:用JWT解码工具解析生成的令牌,确认http://schemas.microsoft.com/ws/2008/06/identity/claims/role(ASP.NET Core对ClaimTypes.Role的默认映射)对应的声明值是否包含User。
  • 确认中间件顺序:确保app.UseAuthentication()在app.UseAuthorization()之前执行,且位于app.UseRouting()之后、app.UseEndpoints()之前。
  • 核对TokenOptions配置:检查appsettings.json中TokenOptions下的Issuer、Audience、SecurityKey是否与令牌生成逻辑中的配置完全一致,任何不匹配都会导致验证失败。
  • 检查请求头格式:确认Authorization头的格式为Bearer {token},无多余空格或拼写错误。
  • 验证角色数据加载:在Login方法中添加调试输出,确认_userDal.GetClaims(userToCheck)确实返回了包含User角色的列表。
  • 启用验证日志:在JWTBearer配置中添加事件日志,查看验证失败的具体原因:
.AddJwtBearer(options =>
{
    // 原有配置...
    options.Events = new JwtBearerEvents
    {
        OnAuthenticationFailed = context =>
        {
            Console.WriteLine($"认证失败:{context.Exception.Message}");
            return Task.CompletedTask;
        },
        OnTokenValidated = context =>
        {
            Console.WriteLine("令牌验证成功");
            return Task.CompletedTask;
        }
    };
});

内容的提问来源于stack exchange,提问作者iremnur memiş

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 20:56:04