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

ASP.NET Core自定义登录代码下JWT认证授权失败问题

问题解决:JWT授权失败(Unprotected token failed)

问题分析

你遇到的Unprotected token failed错误,本质是JWT验证环节无法正确解析或验证Token,核心原因是JWT的签名配置不匹配——你生成Token时用的密钥、算法等参数,和后端验证时的配置不一致,或者验证端根本没配置必要的验证参数。

解决方案

1. 补全JWT验证配置

修改你的ConfigAuth方法,给AddJwtBearer添加完整的验证参数,确保和生成Token时的参数一致:

void ConfigAuth(WebApplicationBuilder builder)
{
    // 从配置文件读取JWT参数(建议存到appsettings.json)
    var jwtSettings = builder.Configuration.GetSection("JwtSettings");
    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings["SecretKey"]));

    builder.Services.AddIdentityApiEndpoints<User>().AddEntityFrameworkStores<MyDBContext>();
    
    builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true,
                ValidIssuer = jwtSettings["Issuer"],
                ValidAudience = jwtSettings["Audience"],
                IssuerSigningKey = key
            };
        });

    builder.Services.AddAuthorization();
    builder.Services.AddAuthorizationBuilder()
        .AddPolicy("admin", policy => policy.RequireRole("admin"))
        .AddDefaultPolicy("user", policy => policy.RequireAuthenticatedUser());
}

同时在appsettings.json中添加JWT配置项:

"JwtSettings": {
  "SecretKey": "你的安全密钥(建议至少32位随机字符串)",
  "Issuer": "你的后端域名",
  "Audience": "你的前端应用标识",
  "ExpiresInMinutes": 60
}

2. 确保中间件顺序正确

在Program.cs中,中间件必须按以下顺序添加:

app.UseAuthentication(); // 先认证
app.UseAuthorization();  // 再授权

// 其他中间件...
app.MapNotesEndpoints();

3. 同步登录接口的Token生成逻辑

检查你登录接口生成JWT的代码,确保使用和验证端一致的密钥、颁发者、受众和算法:

// 示例:正确的JWT生成代码(参考你的登录逻辑调整)
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.UTF8.GetBytes(builder.Configuration["JwtSettings:SecretKey"]);
var tokenDescriptor = new SecurityTokenDescriptor
{
    Subject = new ClaimsIdentity(new[]
    {
        new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
        new Claim(ClaimTypes.Role, user.Role)
        // 其他需要的Claim
    }),
    Expires = DateTime.UtcNow.AddMinutes(Convert.ToDouble(builder.Configuration["JwtSettings:ExpiresInMinutes"])),
    Issuer = builder.Configuration["JwtSettings:Issuer"],
    Audience = builder.Configuration["JwtSettings:Audience"],
    SigningCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
var tokenString = tokenHandler.WriteToken(token);

4. 排查IdentityApiEndpoints的冲突

AddIdentityApiEndpoints会自动添加一套默认的JWT认证配置,如果你自行实现了登录接口,可能会导致配置冲突。如果不需要Identity默认的登录/注册端点,可以移除AddIdentityApiEndpoints,改用AddIdentityCore:

// 替换原有的AddIdentityApiEndpoints
builder.Services.AddIdentityCore<User>(options =>
{
    // 配置Identity选项(如密码规则等)
})
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<MyDBContext>();

关键说明

  • Unprotected token failed通常意味着验证端无法找到正确的密钥来验证Token的签名,所以核心是生成和验证的签名参数必须完全一致。
  • 永远不要硬编码密钥,建议用配置文件管理,生产环境使用环境变量存储敏感信息。

内容的提问来源于stack exchange,提问作者Omid.N

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 14:58:13