如何使用 passport.js 正确实现 serializeUser?

How to properly implement serializeUser with passport.js?

好的,所以我刚刚进入 MEAN 堆栈,我正在尝试使用 Passport.js 构建一个应用程序。

我刚刚开始用户序列化以维护会话。在他们的示例中,Passport 使用此进行序列化和反序列化:

passport.serializeUser(function(user, done) {
  done(null, user.id);
});

passport.deserializeUser(function(id, done) {
  User.findById(id, function(err, user) {
    done(err, user);
  });
});

所以,我的问题是:这个例子是否安全?如果我没有理解错的话,这是否意味着客户端可以伪造用户 ID 以任何拥有该 ID 的用户身份登录?

我想我想问的是,他们的示例是否被认为是 "secure" 和正确的做事方式,或者是否期望您更改这些函数以生成唯一的序列化。如果这被认为是安全的,那么我想我遗漏了一些关于它如何工作的东西,我很乐意被填补。

另一方面,如果这不安全并且我应该编写自己的函数来代替这些函数,那么以下是执行此操作的有效且安全的方法吗:

如果到这里我的逻辑是有效的,那么生成这个随机散列的正确方法是什么?

是的,这就是您进行序列化/反序列化的方式。未从客户端收到 id

会话信息存储在您的本地会话存储中,例如。数据库,在一个随机 ID 下。例如,express-session 使用 uid-safe 生成会话 ID。此 ID 设置为 cookie,然后发送给客户端。

当客户端发出请求时,如果会话 ID 未被篡改,则从 cookie 中读取会话 ID(通常该 ID 使用您在初始化会话时定义的 secret 进行签名)。使用此 ID,可以从本地会话存储中读取真实会话数据。这就是反序列化中使用的id的来源。

这是存储到 MongoDB 的会话对象的示例:

{
  "_id" : "_RXnIfFeb_qH6AXMO2ounrxlJZPHkwda",
  "session" : "{\"cookie\":{\"originalMaxAge\":null,\"expires\":null,\"secure\":false,\"httpOnly\":true,\"path\":\"/\"},\"passport\":{\"user\":\"5614c62e4372842244660dcf\"}}"
}

这里的_id就是cookie中签名发送的内容。解码为 JSON 对象的 session 字符串是:

{
  "cookie": {
    "originalMaxAge": null,
    "expires": null,
    "secure": false,
    "httpOnly": true,
    "path": "/"
  },
  "passport": {
    "user": "5614c62e4372842244660dcf"
  }
}

此处,passport.user 是我的应用程序 seralizeUser 编辑的实际用户 ID seralizeUser,在加载会话时提供给 deserializeUser

那么,如果您更改 cookie 内容会怎样?如果 cookie 已签名,它将失效,因为更改后的值与签名不匹配。如果未签名,则在查询会话存储时使用该值。该查询不会 return 任何东西,因为您更改了 ID 并且数据库中没有匹配的会话(除非您已经找到/猜到了另一个活动会话的会话 ID - 即执行 session hijacking)。