了解护照序列化反序列化


337

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

  1. 叫到哪里user.idpassport.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);
        });
    });

我仍在努力寻找解决方案。我有一个完整的工作应用程序,没有遇到任何类型的错误。

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

任何帮助表示赞赏。

Answers:


450
  1. 叫到哪里user.idpassport.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   
});

2
因此,user.id另存为req.session.passport.useruser本身存储为req.session.passport.user
Anubhav 2014年

@AB我编写了代码以从ID中找到用户,该ID已作为第一个参数传递给反序列化方法。但是在每个请求中,它都是从db中检索用户。这会使db性能下降。我还应该写些什么来反序列化功能,以检查会话中是否存在它?
uzay95 '16

2
@AB我不明白您对uzay95的建议。因此,在我的会话中,我只有user._id。但是在每个请求上,我都必须使用该ID从数据库(也就是findUserByID)中反序列化并将其放入req.user中。如何避免在每个请求上都打这样的电话?
赞科

10
@Zanko您可以将整个用户对象放入会话数据中,但这通常不是一个好主意,因为它可能会有其他副作用。例如,当用户更新他/她的用户名时,您还必须更新会话数据,否则由于“重命名功能损坏”,您将获得票证。那是一个相对无害的例子。权限位或相等的敏感数据也可能发生同样的事情(糟糕...)。本质上,如果您有重复的数据,通常会遇到相同的问题。TL; DR-不要这样做。
Max Truxa

1
如果我没有记错,该req.session.passport.user = {id: '..'}图的一部分是微客,应该是req.session.passport.user = 785352相反,这里785352user.id。我在控制台日志记录方面遇到麻烦,无法证明这一点,但这似乎很有意义。当您调用时done(null, user.id);,采用第二个参数(user.id在这种情况下)并分配给它req.session.passport.user,而不是分配给,是很有意义的req.session.passport.user.id。因为如果您改为通过该user怎么办?req.sesssion.passport.user.id = user没道理
亚当·泽纳

21

对于使用Koa和koa-passport的任何人:

知道在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


很抱歉在这里进行死尸张贴,但在阅读反序列化说明后,我现在确实感到担心。我在这里发布了关于这个问题的SO: stackoverflow.com/questions/54154047/...
彼得·凯尔纳

超级有用,但在从其他路线读取用户时仍然存在一些问题。有谁可以帮我离开这里吗?stackoverflow.com/questions/60709882/...
哈利林肯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.