在MongoDB后端结合.NET Identity的API中禁用Cookie认证并启用JWT认证的问题
我来帮你分析下当前的问题:你使用了AddIdentityMongoDbProvider来集成MongoDB和.NET Identity,但这个方法默认会自动注册Cookie认证方案,哪怕你已经配置了JWT作为默认认证方案,Cookie认证的服务仍然会存在并可能干扰你的API认证流程,导致你想完全用JWT的需求无法实现。下面是具体的解决方案,一步步帮你彻底禁用Cookie认证,只保留JWT:
1. 替换Identity注册方式,避免自动添加Cookie认证
AddIdentityMongoDbProvider内部封装了AddIdentity方法,而AddIdentity默认会添加Cookie认证相关服务。我们改用AddIdentityCore来注册Identity核心服务(用户/角色管理、存储等),这样就不会自动引入Cookie认证了:
// 先获取MongoDB配置 var mongoDbSettings = builder.Configuration.GetSection(nameof(MongoDBSettings)).Get<MongoDBSettings>(); // 用AddIdentityCore替代AddIdentityMongoDbProvider,避免自动注册Cookie认证 builder.Services.AddIdentityCore<ApplicationUser>(options => { // 保留你原来的Identity配置(密码、锁定、用户规则等) options.Password.RequiredLength = 8; options.Password.RequireDigit = true; options.Password.RequireNonAlphanumeric = true; options.Password.RequireUppercase = true; options.Password.RequireLowercase = true; options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30); options.Lockout.MaxFailedAccessAttempts = 20; options.User.RequireUniqueEmail = false; options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#!%&*()^.-_"; // 合并原来的SignIn配置 options.SignIn.RequireConfirmedAccount = false; }) .AddRoles<MongoRole>() // 启用角色支持 .AddMongoDbStores<ApplicationUser, MongoRole, Guid>(mongo => { // 配置MongoDB存储 mongo.ConnectionString = mongoDbSettings?.IdentityConnectionString; mongo.UsersCollection = "Identity"; mongo.RolesCollection = "Roles"; }) .AddDefaultTokenProviders(); // 保留令牌提供者(用于密码重置等功能) // 手动添加SignInManager(AddIdentityCore不会自动注册这个服务) builder.Services.AddScoped<SignInManager<ApplicationUser>>();
2. 移除不必要的Cookie配置
既然我们已经不再注册Cookie认证服务了,原来的ConfigureApplicationCookie代码就完全不需要了,直接删掉这部分:
// 删掉这段代码,现在已经不需要了 // builder.Services.ConfigureApplicationCookie(options => { ... });
3. 确保认证中间件顺序正确
在Program.cs的中间件管道中,必须保证UseAuthentication()在UseAuthorization()之前,并且放在UseRouting()之后、UseEndpoints()之前:
app.UseRouting(); // 认证中间件必须在授权中间件之前 app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
4. 验证JWT角色Claim的一致性
你的JWT认证配置中已经设置了RoleClaimType = ClaimTypes.Role,这是正确的,但要确保生成JWT时添加的角色Claim类型和这个一致。比如你在登录接口生成JWT的代码里,要这样添加角色:
// 从UserManager获取用户角色 var roles = await _userManager.GetRolesAsync(user); // 添加角色Claims时使用ClaimTypes.Role var roleClaims = roles.Select(role => new Claim(ClaimTypes.Role, role));
这样授权策略(比如你的AdminPolicy)才能正确识别用户角色。
5. 测试验证
完成上述修改后,重启API并测试:
- 调用登录接口获取JWT令牌
- 在调用带
[Authorize(Roles = "Admin,SuperAdmin")]的接口时,在请求头中携带Authorization: Bearer <你的JWT令牌> - 查看你配置的认证事件日志,确认只有JWT认证的日志输出,没有Cookie相关的错误
这样就能彻底禁用Cookie认证,完全用JWT来处理你的API授权需求,同时还能保留.NET Identity的用户/角色管理、失败登录锁定等核心功能。
内容来源于stack exchange

