.NET Core 7 API:JS调用如何共享Cookie及JWT替代Session咨询
问题描述
我用.NET Core 7 API开发应用,用户登录时通过以下代码把用户信息存入Session:
public int _UserId { get { if (HttpContext.Session.GetInt32("UserId") == null) { HttpContext.Session.SetInt32("UserId", 0); } return (int)HttpContext.Session.GetInt32("UserId"); } set { HttpContext.Session.SetInt32("UserId", value); } }
用户调用其他API时,程序会自动获取Session处理,这个逻辑在Postman和Swagger UI里运行正常,但用JavaScript调用API时,登录请求和后续的GetCurrentUser请求没法共享Cookie,导致取不到已保存的Session。我的JS调用代码如下:
async function callApiLogin(username, password) { const xhttp = new XMLHttpRequest(); const url = "http://localhost:5296/api/Account/Login"; xhttp.open("POST", url, true); xhttp.setRequestHeader("Content-Type", "application/json"); xhttp.onload = function () { if (xhttp.status === 200) { const response = xhttp.responseText; console.log(response); } else { // Handle error } }; const data = { username: username, password: password, }; xhttp.send(JSON.stringify(data)); } callApiLogin("string1", "string"); console.log("Login completed"); setTimeout(() => { const xhttp = new XMLHttpRequest(); const url = "http://localhost:5296/api/User/GetCurrentUser"; // Replace with the actual API endpoint xhttp.open("GET", url, true); xhttp.setRequestHeader("Content-Type", "application/json"); xhttp.onload = function () { if (xhttp.status === 200) { const response = xhttp.responseText; console.log(response); } else { // Handle error } }; xhttp.send(); }, 5000);
请问如何让JavaScript调用API时像Swagger和Postman一样共享Cookie?是否应该使用JWT替代Session?
解决方案
一、让JS调用共享Cookie的方法
问题核心是跨域请求(CORS)下,浏览器默认不会自动携带Cookie,需要同时在前端和后端配置:
前端修改
在XMLHttpRequest中设置withCredentials = true,这个属性会让请求自动携带当前域名下的Cookie(包括Session对应的Cookie)。修改你的JS代码:
async function callApiLogin(username, password) { const xhttp = new XMLHttpRequest(); const url = "http://localhost:5296/api/Account/Login"; xhttp.open("POST", url, true); // 开启凭证携带 xhttp.withCredentials = true; xhttp.setRequestHeader("Content-Type", "application/json"); xhttp.onload = function () { if (xhttp.status === 200) { const response = xhttp.responseText; console.log(response); } else { // Handle error } }; const data = { username: username, password: password, }; xhttp.send(JSON.stringify(data)); } // 后续请求同样需要开启withCredentials setTimeout(() => { const xhttp = new XMLHttpRequest(); const url = "http://localhost:5296/api/User/GetCurrentUser"; xhttp.open("GET", url, true); xhttp.withCredentials = true; xhttp.setRequestHeader("Content-Type", "application/json"); xhttp.onload = function () { if (xhttp.status === 200) { const response = xhttp.responseText; console.log(response); } else { // Handle error } }; xhttp.send(); }, 5000);
后端配置(.NET Core)
需要在CORS配置中允许携带凭证,并且不能用*通配符指定前端域名:
- 在
Program.cs中配置CORS:
builder.Services.AddCors(options => { options.AddPolicy("AllowFrontend", policy => { // 替换为你的前端实际域名,比如"http://localhost:3000" policy.WithOrigins("http://localhost:你的前端端口") .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials(); // 关键:允许携带凭证 }); }); // 放在app.UseRouting()之后 app.UseCors("AllowFrontend");
- 确保Session配置正确:
builder.Services.AddSession(options => { options.IdleTimeout = TimeSpan.FromMinutes(30); options.Cookie.HttpOnly = true; options.Cookie.IsEssential = true; // 跨域场景下需设置SameSite为None,生产环境需配合HTTPS开启Secure options.Cookie.SameSite = SameSiteMode.None; options.Cookie.SecurePolicy = CookieSecurePolicy.Always; // 开发环境可临时改为None }); // 放在app.UseAuthorization()之前 app.UseSession();
二、是否应该用JWT替代Session?
取决于你的应用场景:
- 适合用Session的场景:
- 单体架构,前后端同域名/子域名部署
- 服务器存储压力小,Session可存在内存或分布式缓存中
- 需要服务器主动失效会话(比如强制用户下线)
- 适合用JWT的场景:
- 复杂跨域的前后端分离架构,或微服务架构
- 不想在服务器存储会话状态,减轻服务器压力
- 需要支持多端登录(Web、APP、小程序),Token可在客户端存储
- 服务需要水平扩展,不依赖Session共享
如果是简单的前后端分离场景,通过上述配置修复Session共享问题即可;如果是分布式或多端需求,JWT会是更合适的选择。
内容的提问来源于stack exchange,提问作者navnforfun
相关产品推荐
相关产品推荐

