Node.js Express + Passport + Cookie 会话 n > 1 个服务器

问题描述 投票:0回答:2

来自护照文档:

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

每个后续请求将不包含凭据,而是包含 标识会话的唯一 cookie。为了支持登录 会话时,Passport 会将用户实例序列化和反序列化为 以及来自会议的内容。

因此,由于身份验证是在客户端浏览器中维护的,我应该能够将 Web 服务器扩展到 > 1(每个服务器使用相同的数据库),并让 Passport 根据存储在 cookie 中的 ID 反序列化用户,无论服务器是否有之前见过该用户。如果服务器 has 之前见过用户但不存在 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.user
req.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.user
req.session
并看看我会期待什么!

现在,有 n > 1 个服务器正在运行,假设有 2 个服务器,如果 Web 应用程序从服务器 2 请求

/
并期望它使用传递的 cookie 中的 ID
req.user
设置
ID
(最初通过登录到服务器1),我什至没有看到调用的反序列化函数!当我将日志记录添加到 HTTP 路由的开头(中间件之后)时:

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

我明白了:

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

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

node.js express cookies passport.js node.js-connect
2个回答
1
投票

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


0
投票

cookie 不包含会话数据,它只包含会话 ID。使用此 ID,您的 Express 应用程序将从其会话存储中获取相关会话数据。由于您在调用

app.use(express.session({ secret: 'keyboard cat' }));
时没有定义存储,因此您正在使用内置内存存储,该内存存储不在进程之间共享。

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

© www.soinside.com 2019 - 2024. All rights reserved.