英文:
Why is my express-session cookie being sent by API but not picked up in browser?
问题
在Express会话中,通过API发送了Cookie,但在浏览器中没有被接收。结果,每次API调用都会生成一个新的会话。
我正在使用Express后端和Vue前端与express-session。我在下面添加了相关代码的简化版本:
const express = require("express");
const cors = require("cors");
const bodyParser = require("body-parser");
const cookieParser = require("cookie-parser");
const session = require("express-session");
app.use(bodyParser.json());
const redis = require("ioredis");
const RedisStore = require("connect-redis").default;
// 配置redis客户端
const redisClient = redis.createClient({
host: "127.0.0.1",
port: 3002,
});
redisClient.on("error", function (err) {
console.log("无法与redis建立连接。" + err);
});
redisClient.on("connect", function (err) {
console.log("成功连接到redis");
});
app.use(
session({
secret: "megaultrasupersecret",
saveUninitialized: true,
store: new RedisStore({ client: redisClient }),
resave: false,
cookie: {
sameSite: "none",
secure: false,
httpOnly: false,
},
})
);
app.use(cookieParser("megaultrasupersecret"));
app.use(
cors({
credentials: true,
origin: ["http://localhost:5173"],
})
);
我已经研究了各种解决方案,例如这个。许多解决方案要求将"secure"设置为false,而我已经这样设置了。
当运行我的服务器时,我设置了express-session的调试模式,可以看到最初设置了Cookie:
express-session saving 3k7qKWwHSuWcz3eE--vQu-EENIvQ0WIk +1ms
express-session set-cookie connect.sid=s%3A3k7qKWwHSuWcz3eE--vQu-EENIvQ0WIk.1i%2Fsaux3bkiyYiKzBVxaMJzqD%2FWbuaACkPwbW4Ql2aA; Path=/; SameSite=None +1ms
但是下次调用我的后端时,日志会显示:
express-session no SID sent, generating session +13ms
我还尝试使用了mongo-store以及Redis作为存储后端。
一些解决方案还要求将"saveUninitialized"设置为false。我已经尝试了两个值,但结果相同。
英文:
Cookie in express session is being sent by API but not picked up in browser. As a result a new session is being generated per API call
I am using express-session with Express backend and Vue frontend.
I have added an abbreviated version of the relevant code below:
const express = require("express");
const cors = require("cors");
const bodyParser = require("body-parser");
const cookieParser = require("cookie-parser");
const session = require("express-session");
app.use(bodyParser.json());
const redis = require("ioredis");
const RedisStore = require("connect-redis").default;
//Configure redis client
const redisClient = redis.createClient({
host: "127.0.0.1",
port: 3002,
});
redisClient.on("error", function (err) {
console.log("Could not establish a connection with redis. " + err);
});
redisClient.on("connect", function (err) {
console.log("Connected to redis successfully");
});
app.use(
session({
secret: "megaultrasupersecret",
saveUninitialized: true,
store: new RedisStore({ client: redisClient }),
resave: false,
cookie: {
sameSite: "none",
secure: false,
httpOnly: false,
},
})
);
app.use(cookieParser("megaultrasupersecret"));
app.use(
cors({
credentials: true,
origin: ["http://localhost:5173"],
})
);
I've researched various solutions such as this one. Many call for 'secure' to be set to false, which I already have.
I set debug mode of express-session when running my server and can see the cookie getting set initially -
express-session saving 3k7qKWwHSuWcz3eE--vQu-EENIvQ0WIk +1ms
express-session set-cookie connect.sid=s%3A3k7qKWwHSuWcz3eE--vQu-EENIvQ0WIk.1i%2Fsaux3bkiyYiKzBVxaMJzqD%2FWbuaACkPwbW4Ql2aA; Path=/; SameSite=None +1ms
But then the next time my backend is called the logs read
express-session no SID sent, generating session +13ms
I also tried using mongo-store as well as Redis as the store.
Various solutions also call for 'saveUninitialized' to be false. I've tried it with both values with the same result.
答案1
得分: 0
因此,我可以看到在响应头中返回了Set-Cookie,并在故障排除过程中更改了许多设置。以下是最终对我有效的设置。我认为关键的变化是在前端使用fetch而不是Axios,并且从后端创建cookie的选项中删除了'samesite': 'None'。如果有人对此有任何额外的反馈,我很好奇 - 不确定为什么Axios不起作用。
BE部分:
app.use(
session({
secret: "megaultrasupersecret",
saveUninitialized: true,
name: "appName",
store: new RedisStore({ client: redisClient }),
resave: false,
cookie: {
maxAge: 1800 * 24,
secure: false,
httpOnly: false,
domain: "localhost",
path: "/",
},
})
);
app.use(cookieParser("megaultrasupersecret"));
app.use(
cors({
credentials: true,
origin: ["http://localhost:5173"],
exposedHeaders: ["set-cookie", "ajax_redirect"],
preflightContinue: true,
methods: ["GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS"],
optionsSuccessStatus: 200,
})
);
FE部分(更新的向后端发起API调用示例):
getRecentlyCreatedForums() {
const recentlyCreatedForums = await fetch('http://localhost:3001/forum', {
method: 'GET',
mode: 'cors',
credentials: 'include'
}).then((data) => data.json().then((data) => data))
英文:
So I could see Set-Cookie being returned in the response header, and ended up changing a whole lot of settings while troubleshooting. Below are the settings that finally worked for me. I think the pivotal change was using fetch on the FE instead of Axios, and taking 'samesite': 'None' out of the options for creating the cookie on the BE. If anybody has any additional feedback on this curious to know - not sure why this didn't work with Axios.
https://developers.google.com/search/blog/2020/01/get-ready-for-new-samesitenone-secure
BE portion:
app.use(
session({
secret: "megaultrasupersecret",
saveUninitialized: true,
name: "appName",
store: new RedisStore({ client: redisClient }),
resave: false,
cookie: {
maxAge: 1800 * 24,
secure: false,
httpOnly: false,
domain: "localhost",
path: "/",
},
})
);
app.use(cookieParser("megaultrasupersecret"));
app.use(
cors({
credentials: true,
origin: ["http://localhost:5173"],
exposedHeaders: ["set-cookie", "ajax_redirect"],
preflightContinue: true,
methods: ["GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS"],
optionsSuccessStatus: 200,
})
);
FE portion (example of updated API call to BE):
getRecentlyCreatedForums() {
const recentlyCreatedForums = await fetch('http://localhost:3001/forum', {
method: 'GET',
mode: 'cors',
credentials: 'include'
}).then((data) => data.json().then((data) => data))
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论