题 了解护照序列化反序列化


您如何解释Passport对外行人序列化和反序列化方法的工作流程。

  1. 哪里 user.id 追求 passport.serializeUser 被称为?

  2. 我们在打电话 passport.deserializeUser 它在哪里适合工作流程?

    // used to serialize the user for the session
    passport.serializeUser(function(user, done) {
        done(null, user.id); 
       // where is this user.id going? Are we supposed to access this anywhere?
    });
    
    // used to deserialize the user
    passport.deserializeUser(function(id, done) {
        User.findById(id, function(err, user) {
            done(err, user);
        });
    });
    

我仍然试图绕过它。我有一个完整的工作应用程序,并没有遇到任何类型的错误。

我只想了解这里到底发生了什么?

任何帮助表示赞赏。


213
2017-12-24 13:22


起源




答案:


  1. user.id在passport.serializeUser被调用之后去哪儿了?

用户ID(您提供的第二个参数) done 函数)保存在会话中,稍后用于通过查找整个对象 deserializeUser 功能。

serializeUser 确定用户对象的哪些数据应该存储在会话中。 serializeUser方法的结果作为附加到会话 req.session.passport.user = {}。例如,它将是(因为我们提供用户ID作为密钥) req.session.passport.user = {id:'xyz'}

  1. 我们正在调用passport.deserializeUser,它在哪里适合工作流程?

第一个论点 deserializeUser 对应于给予的用户对象的键 done 功能(见1.)。因此,您可以借助该密钥检索整个对象。这里的密钥是用户id(密钥可以是用户对象的任何密钥,即名称,电子邮件等)。 在 deserializeUser 该密钥与内存数组/数据库或任何数据资源匹配。

获取的对象作为附加到请求对象 req.user

视觉流程

passport.serializeUser(function(user, done) {
    done(null, user.id);
                 |
});              | 
                 |
                 |____________________> saved to session req.session.passport.user = {id:'..'}
                                   |
                                  \|/           
passport.deserializeUser(function(id, done) {
                   ________________|
                   |
                  \|/ 
    User.findById(id, function(err, user) {
        done(err, user);
                   |______________>user object attaches to the request as req.user

 });
  });

267
2017-12-24 13:28



是的 user.id 保存为 req.session.passport.user 或是 user 本身存储为 req.session.passport.user - Anubhav
@Anubhav编辑见图.. - A.B
说得通。谢谢 - Anubhav
@ A.B我不明白你对uzay95的建议。所以在我的会话中我只有user._id。但是在每个请求中,我都必须使用该id从数据库中反序列化findUserByID,并将其放入req.user中。如何避免每次请求都进行此类呼叫? - Zanko
@Zanko您可以将整个用户对象放入会话数据中,但这通常不是一个好主意,因为它可能有其他副作用。例如,当用户更新他/她的用户名时,您也必须更新会话数据,否则您将因“重命名功能损坏”而获得票证。这是一个相对无害的例子。权限位或相同的敏感数据(Oops ...)也可能发生同样的情况。如果您有重复数据,基本上会遇到相同的问题。 TL; DR - 不要这样做。 - Max Truxa


对于任何使用Koa和 KOA护照

知道用户在serializeUser方法中设置的密钥(通常是该用户的唯一ID)将存储在:

this.session.passport.user

当你进入 done(null, user) 在deserializeUser中,'user'是数据库中的某个用户对象:

this.req.user 要么 this.passport.user

因为某些原因 this.user 在deserializeUser方法中调用done(null,user)时,Koa上下文永远不会被设置。

因此,您可以在调用app.use(passport.session())之后编写自己的中间件,将其放入this.user中,如下所示:

app.use(function * setUserInContext (next) {
  this.user = this.req.user
  yield next
})

如果你不清楚serializeUser和deserializeUser是如何工作的,那就在twitter上点击我吧。 @yvanscher


14
2017-08-04 19:46



简洁明了的答案 - trdavidson