好吧,我刚刚进入 MEAN 堆栈,并且正在尝试使用 Passport.js 构建一个应用程序。
我刚刚开始用户序列化来维护 session 。在他们的示例中,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 的用户身份登录?
我想我要问的是,他们的示例是否被认为是“安全”和正确的做事方式,或者是否期望您更改这些函数以生成唯一的序列化。如果这被认为是安全的,那么我认为我遗漏了一些关于其工作原理的内容,我很乐意得到补充。
另一方面,如果这不安全并且我需要编写自己的函数来代替这些函数,那么以下是执行此操作的有效且安全的方法:
- 序列化用户后,生成随机哈希并将其放入用户的数据库条目中。随机哈希是代表该用户的序列。
- 反序列化后,在数据库中查找随机哈希并返回相应的用户。如果未找到哈希值,则会抛出某种错误。
- 当用户注销时,从数据库条目中删除其序列哈希。
如果到目前为止我的逻辑是有效的,那么生成此随机哈希的正确方法是什么?
最佳答案
是的,这就是序列化/反序列化的方式。未从客户端收到 id
。
session 信息存储到您的本地 session 存储中,例如。数据库,在随机 ID 下。例如,express-session
使用 uid-safe生成 session ID。该 ID 设置为 cookie,然后发送到客户端。
当客户端发出请求时,如果 session ID 未被篡改,则会从 cookie 中读取 session ID(通常该 ID 是使用您在初始化 session 时定义的 secret
进行签名的)。使用此 ID,可以从本地 session 存储中读取真实的 session 数据。这就是反序列化中使用的 id
的来源。
以下是存储到 MongoDB 的 session 对象的示例:
{
"_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,在加载 session 时将其提供给 deserializeUser
.
那么如果更改 cookie 内容会发生什么情况?如果 cookie 已签名,它将失效,因为更改后的值与签名不匹配。如果未签名,则在查询 session 存储时使用该值。该查询不会返回任何内容,因为您更改了 ID 并且数据库中没有匹配的 session (除非您找到/猜测了另一个事件 session 的 session ID - 即执行 session hijacking )。
关于node.js - 如何使用passport.js正确实现serializeUser?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32962225/