ASP.NET Core Web API中JWT认证失效问题求助
核心问题现象
登录接口返回成功,AccessToken和RefreshToken已存入HttpOnly Cookie,但访问带[Authorize]特性的路由时无效,User.Identity.IsAuthenticated始终返回false;手动校验JWT的exp、aud、iss均正常,且JwtBearerEvents无控制台输出。
排查与修复方案
1. 前端未正确传递Cookie(跨域场景)
原因:HttpOnly Cookie需要前端主动携带,跨域下浏览器默认不会发送Cookie;同时SameSite属性设置为Strict时,跨域请求会被限制传递Cookie。
修复:
- 前端请求开启凭证携带:比如Axios请求时添加配置
{ withCredentials: true } - 动态调整Cookie的
SameSite和Secure属性:var cookieOptions = new CookieOptions { HttpOnly = true, Secure = app.Environment.IsProduction(), // 开发环境设为false,避免HTTP下Cookie不发送 SameSite = app.Environment.IsProduction() ? SameSiteMode.Strict : SameSiteMode.Lax, Expires = DateTime.UtcNow.AddMinutes(60) };
2. OnMessageReceived事件未触发(Token未被中间件读取)
原因:JWT中间件默认从Authorization头读取Token,你的Token存在Cookie中,但事件未执行,大概率是开发环境下Secure=true导致Cookie未被浏览器发送(HTTP环境下Secure Cookie不会被传递)。
修复:
- 开发环境临时关闭
Secure属性(如上一步代码) - 增强
OnMessageReceived的日志输出,确认是否读取到Cookie:OnMessageReceived = context => { Console.WriteLine($"Request Path: {context.Request.Path}"); if (context.Request.Cookies.TryGetValue("AccessToken", out var token)) { Console.WriteLine($"Found AccessToken in Cookie: {token.Substring(0, 20)}..."); context.Token = token; } return Task.CompletedTask; }
3. ClaimsIdentity未设置认证类型
原因:生成Token时,ClaimsIdentity未指定认证类型,导致JWT验证通过后无法正确标记用户为已认证。
修复:
在GenerateTokenString方法中,创建ClaimsIdentity时指定与JWT认证Scheme一致的类型:
var claims = new List<Claim> { new Claim(ClaimTypes.NameIdentifier, user.UserName!), new Claim(ClaimTypes.Role, "Admin"), new Claim("TokenId", tokenId) }; // 添加认证类型,匹配JWT认证Scheme var identity = new ClaimsIdentity(claims, JwtBearerDefaults.AuthenticationScheme); var tokenDescriptor = new SecurityTokenDescriptor { Subject = identity, // 其他配置保持不变 };
4. Swagger测试未携带Cookie
原因:Swagger UI默认不会自动携带Cookie,导致测试[Authorize]接口时无Token。
修复:
配置Swagger支持Cookie认证:
builder.Services.AddSwaggerGen(options => { options.AddSecurityDefinition("CookieAuth", new OpenApiSecurityScheme { Type = SecuritySchemeType.ApiKey, Name = "Cookie", In = ParameterLocation.Cookie, Description = "JWT AccessToken stored in HttpOnly Cookie" }); options.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "CookieAuth" } }, new string[] {} } }); });
5. 中间件顺序校验
原因:中间件顺序错误会导致认证逻辑不生效,正确顺序应为:UseHttpsRedirection → UseCors → UseAuthentication → UseAuthorization
修复:
调整Program.cs中的中间件顺序:
var app = builder.Build(); app.UseDefaultFiles(); app.UseStaticFiles(); app.UseHsts(); if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseCors("AllowSpecificOrigin"); // CORS需放在认证中间件之前 app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.MapFallbackToFile("/index.html"); app.Run();
内容的提问来源于stack exchange,提问作者razvan bordinc

