来自护照文档:
在典型的 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。
作为服务器端数据库的替代方案,您可以将会话数据存储在加密的 cookie 中,例如 Mozilla 使用的 cookie:https://github.com/mozilla/node-client-sessions。这比任何服务器端数据库都更具可扩展性,但您必须保持 cookie 的大小相当小。如果我有更多时间,我会给你写一个演示,但现在我只是把这个作为一个问题来回过头来讨论。
cookie 不包含会话数据,它只包含会话 ID。使用此 ID,您的 Express 应用程序将从其会话存储中获取相关会话数据。由于您在调用
app.use(express.session({ secret: 'keyboard cat' }));
时没有定义存储,因此您正在使用内置内存存储,该内存存储不在进程之间共享。
因此,安装任何使用数据库的会话存储,例如。 connect-mongo 用于 MongoDB。