【发布时间】:2021-06-14 06:58:18
【问题描述】:
我正在制作一个网络应用程序。我的后端使用 Node.js、Express.js,具体来说,它使用模块 express-session 为session-based authentication 创建会话对象,以保持用户登录。我了解当我使用 express-session 创建会话时,会在后端创建一个带有会话 ID 的 cookie,并将其发送到前端的浏览器。我已验证当我使用浏览器并访问托管 Express 应用程序的页面(在我的情况下为 localhost:3001)时,此 cookie 会无缝发送。
// My Express app's index.js file
// This code seamlessly sends a session ID cookie to the browser when I visit http://localhost:3001
const express = require('express');
const session = require('express-session');
const mongoDbStore = require('connect-mongodb-session')(session);
const app = express();
const store = new mongoDbStore({
uri: 'mongodb://localhost:27017/GameDB',
collection: 'UserSessions'
});
store.on('error', (err) => {
console.log('Something exploded:' + err);
});
app.use(session({
secret: 'I am stuck, help me please!',
store: store,
saveUninitialized: true,
resave: false,
} ));
app.listen(3001, () => {
console.log('server started on 3001');
})
我得到我的饼干就好了。这是我的 Chrome 开发者工具中的截图:
但是,我希望我的前端是一个单独的应用程序(我正在使用 React),并且我想使用来自前端的 API 请求来访问我后端的所有内容。由于前端和后端是独立的应用程序,它们需要在不同的端口上运行。我的前端将在 3000 端口上运行,而我的后端将继续在 3001 端口上运行。考虑到这一点,我将在浏览器中运行 localhost:3000 而不是 localhost:3001。
唯一的问题是,通过这些更改,express-session 生成的 cookie 不再发送到我的浏览器,即使我从前端到后端执行 HTTP POST(通过 JavaScript fetch())并且得到一个有效的回应。
简而言之,我的问题是:当我为前端使用单独的应用程序时,如何将我的快速会话会话 ID cookie 保存到浏览器中?
这是我的前端 API 请求:
fetch('http://localhost:3001/gimmecookie', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
body: JSON.stringify({ data: "data" })
})
.then(response => response.json() )
.then(response => {
console.log(response)
})
.catch((error) => {
console.error(error);
});
这里是我的 Express 应用程序的 index.js 文件稍作修改:
// My Express app's index.js file that *should* create and
// send a session-id cookie to my React project
const express = require('express');
const cors = require('cors');
const session = require('express-session');
const mongoDbStore = require('connect-mongodb-session')(session);
const app = express();
const corsOptions = {
origin: 'http://localhost:3000',
}
const store = new mongoDbStore({
uri: 'mongodb://localhost:27017/GameDB',
collection: 'UserSessions'
});
store.on('error', (err) => {
console.log('Something exploded:' + err);
});
app.use(cors(corsOptions));
app.use(session({
secret: 'I am stuck, help me please!',
store: store,
saveUninitialized: true,
resave: false,
}));
app.post('/gimmecookie', (req, res) => {
res.json({ sendsome: "data" })
});
app.listen(3001, () => {
console.log('server started on 3001');
});
现在,我正在使用 hack 发送 cookie(在 JS 中创建一个 cookie 并手动发送),但是随着我的项目越来越大,hack 变得越来越烦人。当我只使用一个应用程序时,我需要在此代码中添加什么才能让 cookie 发送? express-session 不是为此设计的吗? (似乎是这样,我知道前端和后端都有单独的应用程序是非常普遍的。)
如果前端和后端有任何形式的握手,我应该期望 cookie 自动发送吗?我是否需要弄乱快速会话初始化对象中的cookie.domain 或cookie.sameSite 属性?我需要弄乱 CORS 或 fetch() Accept 标头吗? res.json() 是不是用错了方法?处理真实IP而不是localhost更容易吗?我已经尝试了很多东西,但无论我做什么,我都无法在我的浏览器上获取那个该死的 express-session 生成的会话 ID cookie。
【问题讨论】:
-
另外,我知道有人问过类似的问题,但我发布了这个问题,因为其他问题存在一些关键差异,并且通常没有好的(或任何)答案。这是一个问类似问题的问题,但使用与 express-session 不同的模块:stackoverflow.com/questions/62096877/…
-
如果您根据需要从浏览器中的端口 3000 访问并且代码使 xhr 到 3001 它应该可以正常工作,您的图像显示您在端口 3001 上,尽管我不确定您为什么想要这个,当您上线时,您想要一个反向代理,您不会想要使用差异端口,最好只针对您的应用程序的单个入口点
-
@LawrenceCherone,你的评论并没有完全回答我的问题,但它让我指向了正确的方向,所以谢谢你。看我的回答。
标签: javascript reactjs express session-cookies mern