ASP.NET 7 Web API身份认证失效:Token被忽略致401错误
.NET 7 API JWT认证401问题排查与修复
我正在开发一个为移动应用提供服务的.NET 7 API项目,一整天都卡着没进展,找的示例全跑不起来。现在所有接口调用都返回401错误,只有标记了[AllowAnonymous]的接口能正常访问。我从微软示例里抄了Token生成方法,能成功拿到Token,但用这个Token调用接口还是返回401,肯定是配置哪里出问题了,相关配置代码如下:
var builder = WebApplication.CreateBuilder(args); // Add services to the container. var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found."); builder.Services.AddDatabaseDeveloperPageExceptionFilter(); builder.Services.AddControllersWithViews(); builder.Services.AddDbContext<Take5Context>(options => options.UseSqlServer(connectionString)); builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))); builder.Services.AddIdentity<IdentityUser, IdentityRole>() .AddEntityFrameworkStores<ApplicationDbContext>() .AddDefaultUI() .AddDefaultTokenProviders(); builder.Services.AddScoped<JwtHandler>(); builder.Services.AddAuthentication(k => { k.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; k.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }).AddJwtBearer(p => { var key = Encoding.UTF8.GetBytes("JWTToken:key"); p.SaveToken = true; p.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = false, ValidateAudience = false, ValidateLifetime = false, ValidateIssuerSigningKey = true, ValidIssuer = "JWKToekn:key", ValidAudience = "JWKToekn:Audience", IssuerSigningKey = new SymmetricSecurityKey(key) }; }); builder.Services.AddAuthorization(options => { options.FallbackPolicy = new AuthorizationPolicyBuilder() .RequireAuthenticatedUser() .Build(); }); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseMigrationsEndPoint(); } else { app.UseExceptionHandler("/Home/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); app.MapRazorPages(); app.Run();
核心问题点
- 密钥读取错误:你直接把配置键名
"JWTToken:key"当成了密钥内容,应该从配置文件中读取对应的值,而不是硬编码这个字符串。 - 拼写错误:
ValidIssuer和ValidAudience写成了"JWKToekn:key"和"JWKToekn:Audience",不仅拼写错了(JWK→JWT,Toekn→Token),而且应该指向配置文件中对应的Issuer和Audience项,不是密钥。 - 生命周期验证关闭:
ValidateLifetime = false会导致Token永远不会过期,既不安全,也可能导致验证逻辑异常,测试阶段也建议开启。 - 配置不匹配:生成Token时使用的密钥、Issuer、Audience必须和验证配置完全一致,哪怕关闭了Issuer/Audience验证,不一致也可能引发潜在问题。
修正后的配置代码
var builder = WebApplication.CreateBuilder(args); // Add services to the container. var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found."); builder.Services.AddDatabaseDeveloperPageExceptionFilter(); builder.Services.AddControllersWithViews(); builder.Services.AddDbContext<Take5Context>(options => options.UseSqlServer(connectionString)); builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))); builder.Services.AddIdentity<IdentityUser, IdentityRole>() .AddEntityFrameworkStores<ApplicationDbContext>() .AddDefaultUI() .AddDefaultTokenProviders(); builder.Services.AddScoped<JwtHandler>(); // 修正JWT认证配置 builder.Services.AddAuthentication(k => { k.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; k.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }).AddJwtBearer(p => { // 从配置文件读取实际密钥 var key = Encoding.UTF8.GetBytes(builder.Configuration["JWTToken:key"] ?? throw new InvalidOperationException("配置中未找到JWTToken:key")); p.SaveToken = true; p.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, // 读取配置中的Issuer和Audience,确保和生成Token时一致 ValidIssuer = builder.Configuration["JWTToken:Issuer"], ValidAudience = builder.Configuration["JWTToken:Audience"], IssuerSigningKey = new SymmetricSecurityKey(key) }; }); builder.Services.AddAuthorization(options => { options.FallbackPolicy = new AuthorizationPolicyBuilder() .RequireAuthenticatedUser() .Build(); }); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseMigrationsEndPoint(); } else { app.UseExceptionHandler("/Home/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); // 中间件顺序必须正确:先认证,再授权 app.UseAuthentication(); app.UseAuthorization(); app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); app.MapRazorPages(); app.Run();
额外检查项
- 配置文件补充:确保
appsettings.json中包含正确的JWT配置:
{ "JWTToken": { "key": "至少16位长度的安全密钥,比如abcdefghijklmnopqrstuvwx", "Issuer": "YourApiName", "Audience": "MobileAppClient" } }
- Token生成代码验证:确保生成Token时使用的参数和验证配置一致,示例代码:
public string GenerateToken(IdentityUser user) { var tokenHandler = new JwtSecurityTokenHandler(); var key = Encoding.UTF8.GetBytes(_configuration["JWTToken:key"]); var tokenDescriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity(new[] { new Claim(ClaimTypes.NameIdentifier, user.Id), new Claim(ClaimTypes.Name, user.UserName) }), Expires = DateTime.UtcNow.AddHours(1), Issuer = _configuration["JWTToken:Issuer"], Audience = _configuration["JWTToken:Audience"], SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature) }; var token = tokenHandler.CreateToken(tokenDescriptor); return tokenHandler.WriteToken(token); }
请求格式检查:调用接口时必须在请求头中添加
Authorization: Bearer {你的Token},注意Bearer后面有一个空格,且Token没有截断。Token解析验证:用JWT解析工具查看生成的Token,确认
iss、aud、exp字段和配置一致,且签名验证通过。
内容的提问来源于stack exchange,提问作者cgraus
相关产品推荐
相关产品推荐

