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

ASP.NET Core 8 Web API JWT Token认证失败(401未授权)求助

JWT认证下[Authorize]特性返回401问题排查

问题场景

使用[Authorize]特性保护FastaController的Get端点时,调用会直接返回401 Unauthorized错误;但移除[Authorize]特性后,能通过HttpContext.User正确识别用户身份,说明JWT令牌解析正常,但认证流程未生效。

相关代码与配置

受保护的API控制器

[Authorize]
[Route("[controller]")]
public class FastaController : Controller
{
   [HttpGet()]
   public async Task<IActionResult> Get(int page = 1, string search = "", int pageSize = 25)
   {
      // 数据获取逻辑
   }
}

appsettings.json中的JWT配置

"JwtTokenSettings": {
    "Key": "fc746b61cde4f6665d3f9791446cd5395661860c0075a905ed9810b7391af467",
    "Issuer": "Comply",
    "Audience": "comply",
    "ExpiryHours": 24
}

JWT令牌生成服务

public class JwtTokenService : IJwtTokenService
{
    private readonly IOptions<JwtTokenSettings> jwtTokenSettings;

    public JwtTokenService(IOptions<JwtTokenSettings> jwtTokenSettings)
    {
        this.jwtTokenSettings = jwtTokenSettings;
    }

    public string GenerateToken(Guid userId, string userEmail)
    {
        string secretKey = jwtTokenSettings.Value.Key;
        string issuer = jwtTokenSettings.Value.Issuer;
        string audience = jwtTokenSettings.Value.Audience;
        var expiryHours = jwtTokenSettings.Value.ExpiryHours;

        var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey));
        var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);

        var claims = new[]
        {
            new Claim(JwtRegisteredClaimNames.Sub, userId.ToString()),
            new Claim(JwtRegisteredClaimNames.Email, userEmail),
            new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
        };

        var token = new JwtSecurityToken(
            issuer: issuer,
            audience: audience,
            claims: claims,
            expires: DateTime.UtcNow.AddHours(expiryHours),
            signingCredentials: credentials
        );

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

Program.cs中的服务配置

var builder = WebApplication.CreateBuilder(args);

builder.Services.Configure<JwtTokenSettings>(
    configuration.GetSection("JwtTokenSettings")
);

var jwtSettings = builder.Configuration.GetSection("JwtTokenSettings");
var key = Encoding.UTF8.GetBytes(jwtSettings["Key"]);

builder.Services.AddSingleton<IJwtTokenService, JwtTokenService>();
builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateLifetime = true,
        ValidateIssuerSigningKey = true,
        ValidIssuer = jwtSettings["Issuer"],
        ValidAudience = jwtSettings["Audience"],
        IssuerSigningKey = new SymmetricSecurityKey(key)
    };
});

问题原因与解决方案

核心原因

Program.cs中仅配置了认证服务,但未在请求管道中启用认证和授权中间件,导致[Authorize]特性无法触发认证逻辑,直接返回401。

解决方案

  1. 添加认证与授权中间件到请求管道
    在Program.cs的管道配置部分,确保UseAuthentication()和UseAuthorization()在UseRouting()之后、UseEndpoints()之前添加,顺序不能颠倒:
var app = builder.Build();

// 其他中间件(如UseHttpsRedirection)
app.UseHttpsRedirection();

app.UseRouting();

// 启用认证和授权中间件
app.UseAuthentication();
app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
});

app.Run();
  1. 可选:验证Claim类型映射(若用户识别仍有问题)
    生成令牌时使用的JwtRegisteredClaimNames.Sub,默认会被JWT中间件映射到ClaimTypes.NameIdentifier,但如果出现映射异常,可手动指定:
  • 方式一:在JWT配置中添加Claim类型映射
.AddJwtBearer(options =>
{
    options.TokenValidationParameters = new TokenValidationParameters
    {
        // 原有配置
        NameClaimType = ClaimTypes.NameIdentifier,
        RoleClaimType = ClaimTypes.Role
    };
})
  • 方式二:生成令牌时直接使用ClaimTypes.NameIdentifier
var claims = new[]
{
    new Claim(ClaimTypes.NameIdentifier, userId.ToString()),
    new Claim(JwtRegisteredClaimNames.Email, userEmail),
    new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
};

内容的提问来源于stack exchange,提问作者Bill Haack

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 02:43:13