ASP.NET Core中JWT已授权但网页端仍返回401问题求助
问题排查与解决方案
核心问题
网页端访问返回401的根本原因是:登录后重定向到User控制器时,没有将JWT Token放入请求的Authorization头中。Postman是手动添加了Bearer Token头才通过认证,而你的代码仅将Token存入数据库,未让前端在后续请求中携带Token完成认证。
具体问题点分析
登录重定向逻辑错误
登录控制器最后返回RedirectToAction("Index", "User", token),会把Token作为查询参数(如/User/Index?token=xxx)传递,但默认JWT Bearer认证只从Authorization请求头读取Token,不会处理查询参数,因此触发401。前端缺少Token存储与携带逻辑
网页端需要将登录获取的Token存储(如localStorage、HttpOnly Cookie),并在请求受保护资源时主动添加Authorization: Bearer {token}头。当前代码未将Token返回给前端存储,直接重定向导致Token丢失。
修复步骤
步骤1:修改登录控制器,返回Token给前端
将登录接口改为返回JSON格式的Token,让前端可获取并存储:
[HttpPost] public IActionResult Index(string inputEmail, string inputPassword) { var user = um.Get(x => x.Email == inputEmail); if (user == null) { return BadRequest("邮箱不存在"); } if (!BCrypt.Net.BCrypt.Verify(inputPassword, user.PasswordHash)) { return BadRequest("密码错误"); } var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_authSettings.Value.Key)); var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256); var jwtSecurityToken = new JwtSecurityToken( issuer: _authSettings.Value.Issuer, audience: _authSettings.Value.Audience, claims: null, expires: DateTime.Now.AddHours(1), notBefore: DateTime.Now, signingCredentials: credentials); var token = new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken); user.Token = token; um.UserUpdate(user); // 返回Token给前端,而非直接重定向 return Ok(new { Token = token, Message = "登录成功" }); }
步骤2:前端处理Token存储与请求头添加
以原生JS为例,前端登录成功后存储Token并跳转:
// 登录请求示例 fetch('/Login/Index', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: `inputEmail=${encodeURIComponent(email)}&inputPassword=${encodeURIComponent(password)}` }) .then(res => res.json()) .then(data => { if (data.Token) { localStorage.setItem('jwtToken', data.Token); // 跳转到User页面 window.location.href = '/User/Index'; } });
后续访问受保护接口时,手动添加请求头:
fetch('/User/Index', { headers: { 'Authorization': `Bearer ${localStorage.getItem('jwtToken')}` } });
步骤3:(推荐)用HttpOnly Cookie存储Token(更安全)
如果是传统MVC项目,建议将Token存入HttpOnly Cookie避免XSS攻击:
- 修改登录控制器添加Cookie:
// 生成Token后添加 Response.Cookies.Append("jwtToken", token, new CookieOptions { HttpOnly = true, Secure = Environment.IsProduction(), // 生产环境启用HTTPS SameSite = SameSiteMode.Strict, Expires = DateTime.Now.AddHours(1) }); return RedirectToAction("Index", "User");
- 配置JwtBearer从Cookie读取Token:
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(x => { x.TokenValidationParameters = new TokenValidationParameters { ValidIssuer = config["JwtSettings:Issuer"], ValidAudience = config["JwtSettings:Audience"], IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(config["JwtSettings:Key"])), ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, }; // 从Cookie读取Token x.Events = new JwtBearerEvents { OnMessageReceived = context => { context.Token = context.Request.Cookies["jwtToken"]; return Task.CompletedTask; } }; });
内容的提问来源于stack exchange,提问作者bart
相关产品推荐
相关产品推荐

