ASP.NET 6 Restful Api Cookie认证无法通过身份验证问题
问题根因
从日志和代码看,认证不生效是4个核心问题叠加导致的:
AddDefaultIdentity方法会自动覆盖你之前手动配置的默认认证方案,内部强制注册名为Identity.Application的Cookie方案作为默认校验方案,你自定义的caloryCookieAuth仅在登录时被使用,后续请求校验身份时根本不会走这个方案,和日志里AuthenticationScheme: Identity.Application was challenged的记录完全对应。- 你是纯RESTful API项目,Cookie认证默认的未授权逻辑是返回302重定向到Razor登录页,但你项目里根本没有对应的Razor页面,才会出现跳转到
/Identity/Account/Login返回404的问题。 - 登录逻辑里手动构造
ClaimsPrincipal的写法绕过了ASP.NET Core Identity的标准认证流程,签发的Cookie不符合Identity的校验规则。 - 用Postman/Fiddler调试时没有开启Cookie自动持久化,登录接口返回的
Set-Cookie头没有被保存,后续请求根本没携带认证Cookie。
修复步骤
1. 修改Program.cs服务配置
删除你之前手动写的AddAuthentication配置块,替换AddDefaultIdentity为AddIdentity(避免默认方案被覆盖),同时配置Cookie认证适配API场景:
builder.Services.AddDbContext<AppDbContext>(o => o.UseSqlServer(builder.Configuration["ConnectionStrings:DefaultConnection"])); // 替换原来的AddDefaultIdentity builder.Services.AddIdentity<IdentityUser, IdentityRole>(options => { options.User.RequireUniqueEmail = true; // 作业不需要邮箱/账号确认,直接关闭 options.SignIn.RequireConfirmedAccount = false; options.SignIn.RequireConfirmedEmail = false; }) .AddEntityFrameworkStores<AppDbContext>() .AddSignInManager() .AddCookie(options => { options.Cookie.Name = "caloryCookieAuth"; // 本地HTTPS调试用Lax即可,None必须配合SecurePolicy.Always使用否则会被浏览器拦截 options.Cookie.SameSite = SameSiteMode.Lax; options.Cookie.HttpOnly = true; options.Cookie.SecurePolicy = CookieSecurePolicy.Always; options.ExpireTimeSpan = TimeSpan.FromDays(1); options.SlidingExpiration = true; // 核心配置:纯API场景禁止302跳转,直接返回标准HTTP状态码 options.Events.OnRedirectToLogin = context => { context.Response.StatusCode = StatusCodes.Status401Unauthorized; return Task.CompletedTask; }; options.Events.OnRedirectToAccessDenied = context => { context.Response.StatusCode = StatusCodes.Status403Forbidden; return Task.CompletedTask; }; });
2. 修正中间件顺序
中间件顺序必须严格按照如下排列,没有自定义Cookie策略的话直接删掉UseCookiePolicy避免拦截Cookie:
app.UseHttpsRedirection(); // app.UseCookiePolicy(); // 无特殊需求注释掉这行 app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.Run();
3. 修正登录/登出接口逻辑
不要手动构造ClaimsIdentity,直接用SignInManager提供的标准方法,自动签发/清理符合Identity规则的认证Cookie:
[AllowAnonymous] [HttpPost("login")] public async Task<ActionResult> LoginAsync([FromBody] LoginModelType loginModelType) { // 直接调用Identity内置的密码校验+登录方法,自动签发Cookie var signInResult = await _signInManager.PasswordSignInAsync( userName: loginModelType.Email, password: loginModelType.Password, isPersistent: false, lockoutOnFailure: false); // 作业场景不需要用户锁定功能直接关闭 if (signInResult.Succeeded) { return NoContent(); } return BadRequest("用户认证失败,请重试!"); } [HttpPost("logout")] public async Task<ActionResult> LogoutAsync() { await _signInManager.SignOutAsync(); return NoContent(); }
4. 调试工具配置
- Postman:开启设置里的
Automatically save and send cookies选项,确保登录接口返回的Cookie被自动存入Cookie Jar,后续同域名请求会自动携带。 - Fiddler:Composer面板开启
Persist cookies选项,自动维护请求Cookie。 - 测试前先清空本地localhost域名下存储的所有旧Cookie,避免历史无效Cookie干扰认证结果。
验证结果
修改完成后重启项目,先调用登录接口返回204,再调用/api/User/getDemoAuthorized接口,会正常返回200和业务数据,未登录时访问会直接返回401状态码,不再出现302跳转和404问题。
内容的提问来源于stack exchange,提问作者MoltenEQ
相关产品推荐
相关产品推荐

