【问题标题】:Node.js Express + Passport + Cookie Sessions n > 1 serversNode.js Express + Passport + Cookie 会话 n > 1 个服务器
【发布时间】:2014-12-05 07:48:30
【问题描述】:

来自 Passport 文档:

在典型的 Web 应用程序中,用于验证 用户只会在登录请求期间传输。如果 身份验证成功,将建立并维护一个会话 通过在用户浏览器中设置的 cookie。

每个后续请求都不会包含凭据,而是 标识会话的唯一 cookie。为了支持登录 会话,Passport 将序列化和反序列化用户实例以 并从会话中。

因此,由于身份验证在客户端的浏览器中维护,我应该能够将 Web 服务器扩展到 > 1(每个服务器使用相同的数据库)并让 Passport 从存储在 cookie 中的 ID 反序列化用户,无论是否服务器以前见过用户。如果服务器 之前见过用户,但不存在 cookie,我希望 Passport 无法通过身份验证...但我什至无法使用 n > 1 个服务器达到那么远。

使用 1 个服务器进程,Passport 工作正常:

服务器或多或少是两台服务器上的文档的逐字记录(经过多次尝试使用连接引用等):

app.configure(function() {
  app.use(express.static('public'));
  app.use(express.cookieParser());
  app.use(express.bodyParser());
  app.use(express.session({ secret: 'keyboard cat' }));
  app.use(passport.initialize());
  app.use(passport.session());
  app.use(app.router);
});

当用户登录成功时,在我返回 HTTP 请求之前,我记录了req.userreq.session

console.log(req.user);
console.log(req.session);
res.send(200, req.user);
// {"cookie":{
//   "originalMaxAge":null,
//   "expires":null,
//   "httpOnly":true,
//   "path":"/"
//  },
//  "passport":{"user":"ID"}}

当 HTTP 请求返回时,Web 应用程序请求 / 并期望服务器从传递的 cookie 中设置 req.user,ID 为 ID

passport.deserializeUser(function(req, user_id, cb) {
  console.info('Passport deserializing user: '
    .concat(user_id));
  console.log(req.user);
  console.log(req.session);
  // ...
  // cb(null, user);
});

有 1 台服务器正在运行,这将记录为:

Passport deserializing user: ID
undefined
undefined

在回调cb(null, user) 之后和我返回请求之前,我立即记录req.userreq.session,看看我会期待什么!

现在,n > 1 个服务器正在运行,假设是 2,如果 Web 应用从服务器 2 请求 / 并期望它从 cookie 中设置 ID 为 IDreq.user通过(最初通过登录服务器 1 设置),我什至没有看到调用的反序列化函数!当我将日志记录添加到 HTTP 路由的开头(在中间件之后):

console.log(req.user);
console.log(req.session);

我明白了:

undefined
// {"cookie":{
//   "originalMaxAge":null,
//   "expires":null,
//   "httpOnly":true,
//   "path":"/"
//  },
//  "passport":{}}

...这告诉我 cookie 出了点问题,但是什么?两个服务器进程都在同一个 DNS 后面的 Heroku 上。我已经阅读了关于为此需要一些“共享会话”存储的各种差异......但这就是客户端浏览器级别的cookie。请帮忙! Express 是最新的 3.X,Passport 是 2.1。

【问题讨论】:

    标签: node.js cookies express connect passport.js


    【解决方案1】:

    cookie 不包含会话数据,它仅包含会话 ID。使用此 ID,您的 Express 应用程序将从其会话存储中获取相关的会话数据。而且由于您在调用app.use(express.session({ secret: 'keyboard cat' })); 时没有定义存储,因此您使用的是不在进程之间共享的内置内存存储。

    所以,安装任何使用数据库的会话存储,例如。 connect-mongo 用于 MongoDB。

    【讨论】:

      【解决方案2】:

      作为拥有服务器端数据库的替代方案,您可以将会话数据存储在加密的 cookie 中,例如 Mozilla 使用的那些:https://github.com/mozilla/node-client-sessions。这比任何服务器端数据库都更具可扩展性,但您必须保持 cookie 的大小相当小。如果我有更多的时间,我会为你写一个演示,但现在我只是把它写下来作为一个问题再回来。

      【讨论】:

        猜你喜欢
        • 2016-01-18
        • 2013-02-07
        • 2014-09-14
        • 2013-03-11
        • 1970-01-01
        • 2020-09-17
        • 1970-01-01
        • 2020-08-20
        • 2014-05-20
        相关资源
        最近更新 更多