2015-10-06 102 views
2

好吧,所以我只是进入MEAN堆栈,并且正在尝试使用Passport.js构建应用程序。如何使用passport.js正确实现serializeUser?

我刚刚开始用户序列化来维护会话。在他们为榜样,Passport使用该序列化和反序列化:

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

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

所以,我的问题是:被认为是安全的这个例子吗?如果我理解这个权利,这是不是意味着客户端可以伪造用户标识以登录为具有该标识的用户?

我猜我问的是,是他们的例子认为是“安全”和做事的正确方法,或者是预期你会改变这些功能来生成唯一的序列化。如果这被认为是安全的,那么我想我缺少这是如何工作的东西,我很乐意在需要填补。

在另一方面,如果这是不是安全的,我希望我写的自己的功能代替这些,下面是这样做的有效和安全的方式:

  • 在用户序列化后,生成一个随机哈希,并把它放在用户的数据库条目。随机哈希是表示该用户的序列号。
  • 反序列化后,查找数据库中的随机散列并返回相应的用户。如果没有发现哈希引发某种错误。
  • 当用户注销时,从其数据库中的条目中删除其串行散列。

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

回答

2

是的,这就是你如何做序列化/反序列化。没有从客户端收到id

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

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

下面是一个例子存储到MongoDB的会话对象可能是什么样子:

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

这里的_id是什么签名,并在cookie被发送。该session字符串,解码JSON对象是:

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

这里,passport.user是我的应用程序seralizeUser正在加载会话时给予deserializeUser返回的实际用户ID。

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

+0

好吧,最终passport.user可以是我想要的任何东西,因为它不会被发送到客户端,对吧? – danielhep

+0

理论上是的,但没有尝试过,如果返回例如。对象或数组工作。 – vesse