.NET Core MVC调用JWT保护的WebAPI始终返回401未授权
我正在开发一个学习用的.NET解决方案,包含.NET Core Web App(MVC)和.NET Core Web API。API中用户登录后生成JWT令牌返回给MVC,期望用该令牌访问GetUsers等受保护资源。但Postman用令牌能正常访问,MVC通过HttpClient携带Bearer令牌调用时始终返回401未授权。
排查与解决方法
1. API地址协议不匹配
API配置的Issuer和Audience是https://localhost:44372/,但MVC的AppSettings.json中baseURLAPI使用的是http://localhost:44372/,协议不一致会导致令牌的Issuer/Audience验证失败。
解决:
修改MVC的AppSettings.json,将baseURLAPI改为https://localhost:44372/,与API配置保持一致。
2. MVC中间件顺序错误
MVC的Startup.cs中UseSession()的位置在UseAuthorization()之后,导致Session无法正确读取令牌。ASP.NET Core中间件顺序要求UseSession()必须在UseRouting()之后、UseAuthentication()之前。
解决:
调整MVC Startup.cs的Configure方法中间件顺序:
app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseSession(); // 移至此处,在认证和授权之前 app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Registration}/{action=Login}/{id?}"); });
3. 令牌被额外序列化/带引号
API返回的令牌可能是带双引号的JSON字符串(例如"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."),MVC直接存储到Session后,携带的令牌会包含无效的引号,导致验证失败。
解决:
在MVC的Login方法中去除令牌前后的引号:
string token = await res.Content.ReadAsStringAsync(); // 清理可能的前后引号 token = token.Trim('"'); HttpContext.Session.SetString("JwtToken", token);
4. API的CORS中间件顺序错误
API的Startup.cs中UseCors()在UseAuthorization()之后,CORS头需要在授权逻辑之前处理,否则跨域请求的令牌头可能被拦截。
解决:
调整API Startup.cs的Configure方法中间件顺序:
app.UseHttpsRedirection(); // 将CORS移至认证和授权之前 app.UseCors(x => x .AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader()); app.UseAuthentication(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
5. 重复添加Authorization头
如果_userAPI.Initial()复用了HttpClient实例,可能残留旧的Authorization头,导致令牌冲突。
优化:
在MVC调用API时先清除旧的授权头:
// 清除原有授权头 client.DefaultRequestHeaders.Authorization = null; client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
内容的提问来源于stack exchange,提问作者aroy3639

