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

时间:2015-10-06 05:17:49

标签: node.js serialization express hash 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的用户身份登录?

我想我要问的是,他们的例子被认为是"安全"和正确的做事方式,或者是否期望您将更改这些功能以生成唯一的序列化。如果这被认为是安全的,那么我想我错过了一些关于它是如何工作的东西,而且我很乐意被填补。

另一方面,如果这不安全并且我希望用自己的函数来代替这些函数,那么以下是一种有效且安全的方法:

  • 在序列化用户时,生成随机哈希并将其放入用户的数据库条目中。随机哈希是表示该用户的序列。
  • 反序列化后,在数据库中查找随机哈希并返回相应的用户。如果找不到哈希会引发某种错误。
  • 当用户注销时,从数据库中的条目中删除其串行哈希。

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

1 个答案:

答案 0 :(得分:2)

是的,这就是你如何进行序列化/反序列化。未收到客户的id

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

当客户端发出请求时,如果cookie未被篡改,则会从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,在加载会话时会向deserializeUser提供。

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