使用passport.js与语法混淆验证?

时间:2016-05-30 02:28:39

标签: javascript node.js express passport.js

在passport.js中有一些我不明白的事情。

1



var passport = require('passport')
  , LocalStrategy = require('passport-local').Strategy;

passport.use(new LocalStrategy(
  function(username, password, done) {
    User.findOne({ username: username }, function (err, user) {
      if (err) { return done(err); }
      if (!user) {
        return done(null, false, { message: 'Incorrect username.' });
      }
      if (!user.validPassword(password)) {
        return done(null, false, { message: 'Incorrect password.' });
      }
      return done(null, user);
    });
  }
));




null函数中done()代表什么。它似乎总是第一个参数,我对实际做的事感到困惑?

2



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

passport.deserializeUser(function(obj, cb) {
  cb(null, obj);
});




序列化和反序列化有什么作用?当会话存储在浏览器中时,是否在登录后调用serialize?反序列化是指访问页面,以便在服务器上反序列化会话以验证该用户?

最后,null

中的cb(null, user);参数又是什么

1 个答案:

答案 0 :(得分:3)

  
      
  1. 在done()函数中表示null。它似乎总是第一个参数,我对实际做的事感到困惑?

         
        
    • cb中的null参数是什么(null,user);
    •   
  2.   

按照惯例,NodeJS使用错误优先回调,这意味着回调函数的第一个参数始终是错误对象。如果您没有任何错误,请传入null。换句话说,如果错误参数为null,则操作成功,如果错误参数不是null,则发生错误。这适用于您询问的所有示例。如果您查看代码,您可以看到您已经在利用这个:

User.findOne({ username: username }, function (err, user) {
  if (err) { 
    // Error happened and passed as first argument
    return done(err); 
  } 

  // ...

  // no error so we pass in null
  return done(null, user);

此外,Passport有其身份验证过程的惯例,正如他们的文档所说:

  

如果凭据有效,则验证回调会调用done以向经过身份验证的用户提供Passport。如果凭据无效(例如,如果密码不正确),则应使用false而不是用户调用done来指示身份验证失败。

这就是你在这里做的事情:

User.findOne({ username: username }, function (err, user) {

  // ...

  if (!user) {
    return done(null, false, { message: 'Incorrect username.' });
  }
  if (!user.validPassword(password)) {
    return done(null, false, { message: 'Incorrect password.' });
  }

  // ...
  
      
  1. 序列化和反序列化有什么作用?当会话存储在浏览器中时,是否在登录后调用serialize?和反序列化是在访问页面时如何在服务器上反序列化会话以验证该用户?
  2.   

好吧,Passport的文档说:

  

如果身份验证成功,将通过用户浏览器中设置的cookie建立和维护会话。每个后续请求都不包含凭据,而是包含标识会话的唯一cookie。为了支持登录会话,Passport将对会话进行序列化和反序列化用户实例。

这意味着,在用户登录后,会调用serializeUser并将您传递给回调的用户数据cb

passport.serializeUser(function(user, cb) {
  cb(null, user); // <-- this user object
});

保存在会话存储区(通常是浏览器cookie)中,并在代码中的req.session.passport.user处可用。

当用户重新连接到您的页面时(通过刷新或离开并返回),相同的数据将作为第一个参数传递给deserializeUser以用于检索用户对象。

passport.deserializeUser(function(obj, cb) {
  cb(null, obj); // <-- obj is the same `user` object you used in serializeUser
});

您在这里做的是将实际的user对象传递给serializeUser中的回调,然后将该同一对象传回deserializeUser中的回调。这意味着您将整个用户对象存储在您的cookie中,这对于玩游戏是可以的,但通常不是一个好主意,因为cookie存储是有限的,而且用户信息通常是敏感的。

执行此操作的典型方法是将用户ID(而非整个用户对象)传递到cb中的serializeUser,以使会话中存储的数据量保持较小。当进一步发出请求时,此id将传递给deserializeUser并用于查找实际的用户对象,通常来自数据库,该对象将恢复为req.user

以下是一个例子:

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

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