ASP.NET Core 7 MVC中JWT认证遇401错误求助
问题分析与解决方案
核心问题
你遇到的401错误主要来自三个关键点:
- 中间件顺序错误:认证、授权中间件的调用顺序不符合ASP.NET Core规范,且缺少路由中间件
- JWT获取逻辑缺失:默认
JwtBearer中间件只会读取Authorization: Bearer <token>请求头,无法识别你存在Cookie中的Token - MVC场景下的方案适配问题:手动将JWT存Cookie并非MVC项目的最优实践,框架内置的Cookie认证更适配服务器端渲染场景
解决方案一:调整JwtBearer配置读取Cookie
如果你坚持使用JWT方案,需要修改配置让中间件从Cookie中获取Token,并修正中间件顺序:
1. 修改Program.cs中的JwtBearer配置
builder.Services .AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, ValidateAudience = false, ValidateIssuer = false, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration.GetSection("AppSettings:JwtSecret").Value!)) }; // 添加从Cookie读取Token的逻辑 options.Events = new JwtBearerEvents { OnMessageReceived = context => { context.Token = context.Request.Cookies["TokenCookie"]; return Task.CompletedTask; } }; });
2. 修正Program.cs的中间件顺序
中间件必须严格遵循以下顺序:
var app = builder.Build(); if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Home/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); // 新增路由中间件,MVC必须依赖该中间件 app.UseRouting(); // 先认证,再授权,顺序不能颠倒 app.UseAuthentication(); app.UseAuthorization(); app.MapControllerRoute( name: "default", pattern: "{controller=Login}/{action=Index}/{id?}"); app.Run();
3. 优化Cookie的安全属性
存储Token时添加安全配置,防止XSS和CSRF攻击:
// 在Authenticate方法中修改Cookie写入逻辑 Response.Cookies.Append("TokenCookie", token, new CookieOptions { HttpOnly = true, // 禁止JS读取Cookie Secure = app.Environment.IsProduction(), // 生产环境仅HTTPS传输 SameSite = SameSiteMode.Strict, // 限制跨站请求携带Cookie Expires = DateTime.Now.AddMinutes(60) });
解决方案二:改用ASP.NET Core内置Cookie认证(推荐MVC场景)
MVC是服务器端渲染项目,使用框架内置的Cookie认证更省心,无需手动处理JWT的生成与存储:
1. 修改Program.cs的认证配置
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => { options.LoginPath = "/Login/Index"; // 未认证时自动跳转登录页 options.ExpireTimeSpan = TimeSpan.FromMinutes(60); // Cookie有效期 options.Cookie.Name = "AuthCookie"; // 自定义Cookie名称 options.Cookie.HttpOnly = true; options.Cookie.SecurePolicy = CookieSecurePolicy.Always; // 生产环境强制HTTPS options.Cookie.SameSite = SameSiteMode.Strict; });
2. 修改Authenticate登录方法
[HttpPost] public async Task<IActionResult> Authenticate(string user, string passwd) { if (someLogic) { // 创建用户身份声明 var claims = new List<Claim> { new Claim(ClaimTypes.Name, user) }; var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); var principal = new ClaimsPrincipal(identity); // 生成认证Cookie await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal, new AuthenticationProperties { ExpiresUtc = DateTime.UtcNow.AddMinutes(60) }); return RedirectToAction("Index", "Home"); } else { TempData["ErrorLogin"] = "Invalid credentials"; return RedirectToAction("Index", "Login"); } }
3. 中间件顺序同方案一
确保UseRouting→UseAuthentication→UseAuthorization的顺序正确。
额外检查项
- 确认
appsettings.json中AppSettings:JwtSecret存在,且长度不少于16字节(HmacSha256算法要求) - 受保护的控制器/Action需添加
[Authorize]属性:[Authorize] public class HomeController : Controller { public IActionResult Index() => View(); }
内容的提问来源于stack exchange,提问作者ram.rs
相关产品推荐
相关产品推荐

