.NET 6中使用cookies.delete无法删除Cookie的问题排查
我在用户登录时设置了两个Cookie,期望登出时将它们删除。目前直接通过Swagger页面调用API的登出方法时,Cookie能被正常删除,但UI和API部署在不同站点(本地环境UI运行在localhost:3000,API运行在localhost:51269),从UI端调用登出方法时,虽然接口返回成功,也能看到响应里Cookie的过期时间已设为1970年,但Cookie实际并没有被删除。
我试过添加Secure=true,也确保删除Cookie时用了和设置时完全一致的配置,但问题依然存在。环境是Chrome 120.0.6099.130,API基于.NET 6,UI用React开发。
登出方法代码
[HttpGet] [Route("Logout")] public IActionResult Logout() { Response.Cookies.Delete("loggedin", new CookieOptions() { HttpOnly = false, SameSite = SameSiteMode.Strict, Secure = true}); Response.Cookies.Delete("token", new CookieOptions() { HttpOnly = true, SameSite = SameSiteMode.Strict, Secure=true }); return Ok(); }
登录时设置Cookie的代码
Response.Cookies.Append("token", tokenString, new CookieOptions() { HttpOnly = true, SameSite = SameSiteMode.Strict, Secure = true, Expires = DateTimeOffset.Now.AddDays(1) }); Response.Cookies.Append("loggedin", "1", new CookieOptions() { HttpOnly = false, SameSite = SameSiteMode.Strict, Secure = true, Expires = DateTimeOffset.Now.AddDays(1) });
浏览器收到的登出响应
Set-Cookie: loggedin=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; secure; samesite=strict Set-Cookie: token=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; secure; samesite=strict; httponly
解决办法
调整
SameSite配置
跨域场景下SameSite=Strict会阻止浏览器处理跨站的Cookie修改请求,将其改为SameSiteMode.None,同时必须保留Secure=true(Chrome要求SameSite=None的Cookie必须是Secure类型)。修改后设置和删除Cookie的代码如下:- 登录时:
Response.Cookies.Append("token", tokenString, new CookieOptions() { HttpOnly = true, SameSite = SameSiteMode.None, Secure = true, Expires = DateTimeOffset.Now.AddDays(1) }); Response.Cookies.Append("loggedin", "1", new CookieOptions() { HttpOnly = false, SameSite = SameSiteMode.None, Secure = true, Expires = DateTimeOffset.Now.AddDays(1) }); - 登出时:
Response.Cookies.Delete("loggedin", new CookieOptions() { HttpOnly = false, SameSite = SameSiteMode.None, Secure = true}); Response.Cookies.Delete("token", new CookieOptions() { HttpOnly = true, SameSite = SameSiteMode.None, Secure=true });
- 登录时:
API端配置CORS允许凭证
在.NET 6的CORS配置中开启允许携带凭证,确保跨域请求能传递Cookie:builder.Services.AddCors(options => { options.AddPolicy("AllowReactApp", policy => policy.WithOrigins("https://localhost:3000") .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials()); });注意:本地开发如果UI用的是http协议,
Secure=true的Cookie不会被浏览器发送,此时可以临时在开发环境将Secure设为false(生产环境必须设为true),或者给UI启用https(比如使用https-localhost工具)。React请求时携带凭证
调用登出接口时,必须设置credentials: 'include',确保请求携带Cookie:fetch('https://localhost:51269/Logout', { method: 'GET', credentials: 'include' })
内容的提问来源于stack exchange,提问作者T.Rhodes

