ASP.NET Core Web API携带Bearer Token却无法识别用户登录状态
问题解决:Bearer Token携带但用户未认证的修复方案
核心问题诊断
你的代码存在两个关键问题导致认证失效:
- 中间件顺序错误:身份认证/授权中间件必须在端点映射之前执行,否则Token验证逻辑不会生效
- 未指定默认认证方案:
AddAuthentication未明确使用Bearer Token作为默认验证方案,导致系统无法识别携带的Token
1. 修正Program.cs的认证配置与中间件顺序
修改Program.cs中的认证服务注册和中间件顺序,这是解决问题的核心:
using Microsoft.AspNetCore.Identity; using MongoDB.Bson; var builder = WebApplication.CreateBuilder(args); var settings = new DatabaseSettings { ConnectionString = Environment.GetEnvironmentVariable("MONGO_CONNECTION_STRING") ?? builder.Configuration.GetSection("Database")["ConnectionString"], DatabaseName = builder.Configuration.GetSection("Database")["DatabaseName"], CollectionName = builder.Configuration.GetSection("Database")["CollectionName"] }; builder.Services.Configure<DatabaseSettings>(options => { options.ConnectionString = settings.ConnectionString; options.DatabaseName = settings.DatabaseName; options.CollectionName = settings.CollectionName; }); // 明确指定默认认证方案为Bearer Token builder.Services.AddAuthentication(IdentityConstants.BearerScheme) .AddBearerToken(IdentityConstants.BearerScheme); builder.Services.AddAuthorizationBuilder(); builder.Services.AddIdentityCore<User>().AddApiEndpoints(); builder.Services.AddIdentity<User, Role>() .AddMongoDbStores<User, Role, ObjectId>( settings.ConnectionString, settings.DatabaseName ) .AddDefaultTokenProviders(); builder.Services.AddSingleton<UserService>(); builder.Services.AddControllers(); // 添加CORS配置(解决跨域问题) builder.Services.AddCors(options => { options.AddPolicy("AllowFrontend", policy => { policy.WithOrigins("http://localhost:3000") // 替换为你的Next.js前端地址 .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials(); }); }); var app = builder.Build(); app.UseHttpsRedirection(); app.UseCors("AllowFrontend"); // 跨域中间件放在认证之前 // 先执行认证、授权中间件,再映射端点 app.UseAuthentication(); app.UseAuthorization(); app.MapIdentityApi<User>(); app.MapControllers(); app.Run();
2. 优化UserController的认证状态验证
修改UserController的Get方法,增加认证用户信息的输出,方便调试:
[Authorize] [ApiController] [Route("api/[controller]")] public class UserController : ControllerBase { private readonly UserService _userService; public UserController(UserService userService) => _userService = userService; [HttpGet("{username}")] public async Task<ActionResult<Object>> Get(string username) { var user = await _userService.GetAsync(username); if (user is null) { return NotFound(); } // 获取认证用户的用户名,确认Token解析是否正确 var authenticatedUsername = User.Identity?.Name; bool isLoggedInUser = User.Identity.IsAuthenticated; Console.WriteLine($"当前认证用户:{authenticatedUsername},是否已认证:{isLoggedInUser}"); return new { user, isLoggedInUser, authenticatedUsername }; } }
3. 前端请求的跨域优化
在Next.js的UserDashboard组件中,给fetch请求添加跨域凭证配置:
const res = await fetch(`http://127.0.0.1:5109/api/user/${username}`, { method: 'GET', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}`, }, credentials: 'include' // 允许跨域携带凭证 });
内容的提问来源于stack exchange,提问作者BeeFriedman
相关产品推荐
相关产品推荐

