【问题标题】:Saving session data across multiple node instances跨多个节点实例保存会话数据
【发布时间】:2017-08-21 08:50:30
【问题描述】:

编辑 - 2017 年 10 月 22 日
我们的会话没有持续存在的原因不止一个,我不得不将我们的
快速会话选项更改为:

api.use(session({
    secret: 'verysecretsecret',
    resave: false,
    saveUninitialized: false,
    cookie: {
        path: '/',
        httpOnly: true,
        domain: 'domain.dev',
        maxAge: 1000 * 60 * 24
    },
    store: new MongoStore({ mongooseConnection: mongoose.connection, autoReconnect: true })
}));

显然domain: 'localhost' 导致 express-session 每次有人启动会话时都会启动一个新会话,然后当您有一个单独的节点实例用于会话处理时刷新/导航回来。

我通过执行以下操作解决了这个问题:

  1. 已将 127.0.0.1 domain.dev 添加到我的 hosts 文件中,该文件位于 C:\Windows\System32\drivers\etc
  2. 根据下面给出的答案,我需要一个存储会话的地方,因此我们选择了 MongoDB。这意味着我必须在我的快速会话选项中添加以下内容:

    store: new MongoStore({ mongooseConnection: mongoose.connection, autoReconnect: true })

  3. 在 express-session 选项中添加了 httpOnly: true 属性。
  4. 因为我们使用 jQuery 处理 ajax 请求,所以在调用后端之前,我必须在前端 Web 应用程序中启用一些设置:

    $.ajaxSetup({ xhrFields: { withCredentials: true }, crossDomain: true, });


原始帖子
我目前正在开发一个平台,该平台决定让 API 在端口 3001 上运行,而 Web 应用程序本身在端口 3000 上运行。做出这个决定是为了更容易监控流量。

现在,我们谈论的是 express 应用程序,所以我们默认使用 express-session npm 包。我想知道是否有可能保存存储在运行在端口 3001 上的节点实例上的会话数据,并由运行在端口 3000 上的节点实例检索,如果这有意义的话。

详细来说,这是我们的用户身份验证流程:

  1. 用户导航到我们在端口 3000 上运行的 Web 应用程序。
  2. 然后用户登录,向在端口 3001 上运行的 API 发送 POST 请求,当凭据正确时存储会话数据,发送响应以便 Web 应用知道用户已通过身份验证。
  3. 用户在关闭浏览器后刷新页面或返回 Web 应用程序,因此 Web 应用程序失去身份验证状态。因此,在加载时,它总是向端口 3001 上的 API 发送 GET 请求,以检查是否有可用的会话数据,这意味着用户已登录,因此我们可以让 Web 应用知道用户已通过身份验证。

(如果我的思路有问题,请告诉我)

问题在于执行此操作时 express-session 似乎不起作用。 我已启用 CORS,因此 Web 应用程序能够向 API 发送请求。这就是 express-session 配置的样子:

api.use(session({
    secret: 'verysecretsecret',
    resave: false,
    saveUninitialized: false,
    cookie: {
        path: '/',
        domain: 'localhost',
        maxAge: 1000 * 60 * 24
    }
}));

最好在不使用 Redis 之类的东西的情况下帮助我解决这个问题,我只是想知道是否可以仅使用 express-session 和节点来解决这个问题。

【问题讨论】:

  • 您所说的“似乎不起作用”是什么意思
  • 您在寻找粘性会话吗?使用 redis,将用户数据存储在 redis 中,让所有 express 实例与 redis 实例对话。
  • @robertklep 似乎没有工作 我的意思是会话丢失了,所以假设我设置req.session.user = 'john'; 然后在关闭会话后检查我的会话浏览器用户道具不存在,换句话说,会话丢失。 @Niraj 是的,我正在寻找粘性会话,但我只是想知道在不使用 Redis 之类的数据库的情况下这是否可以实现。
  • @KevinKarsopawiro 是您使用withCredentials 的客户端代码吗?如果没有,那么它不会向 API 服务器发送任何 cookie。

标签: node.js express session cross-domain express-session


【解决方案1】:

最好在不使用 Redis 之类的东西的情况下帮助我解决这个问题

您希望我们帮助您解决这个问题,最好不要使用适合工作的工具。

如果没有 Redis,您将需要使用其他数据库。如果没有“类似 Redis 的东西”(即没有数据库),您将需要实现一些其他方式来处理数据库的书籍示例用例。

如果您要使用数据库,那么使用 Redis 或 Memcached 之类的数据库对于几乎每个请求都需要快速访问数据的事情是最合理的。如果您使用比这更慢的数据库,您的应用程序的性能将受到极大的影响。

我只是想知道是否可以仅使用 express-session 和节点来解决此问题。

是的。尤其是当您将 express-session 与 Redis 一起使用时,正如 express-session 模块的文档中所建议的那样:

如果您的所有实例都在同一台机器上工作,那么您可以使用 SQLite 之类的数据库将数据存储在文件系统中,但即使您的所有实例都在同一个机器上,我的建议仍然是使用 Redis,因为它会更简单,性能更高,并且在您需要横向扩展的情况下,它会很容易做到。

此外,如果您的所有会话数据都可以毫无问题地放入 cookie,那么您可以使用此模块:

这会将所有会话数据存储在 cookie 中。 (感谢 Robert Klep 在 cmets 中指出这一点。)

【讨论】:

  • 还有cookie-session 将整个会话存储在(签名的)cookie 中。
  • 是否有 2 个快速应用程序在不同的端口上运行,使用相同的 Redis 实例进行会话存储也可以工作?我不完全明白的是:从快速应用程序 2 中检索它时,在快速应用程序 1 上设置 req.session.user = 'john'; 是否会持续存在?如果是,那么很高兴知道,但我只是问是否可以不使用数据库 - 只使用基本的 express-session 包,但我仍然会接受你的帖子作为答案。
猜你喜欢
  • 1970-01-01
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
  • 2020-03-14
  • 1970-01-01
  • 2019-12-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多