You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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配置中允许携带凭证,并且不能用*通配符指定前端域名:

  1. 在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");
  1. 确保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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 22:14:53