Auth using passport.js 与语法混淆?

Auth using passport.js confusion with syntax?

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);
    });
  }
));

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

2.

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

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

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

最后 cb(null, user);

中的 null 参数是什么
  1. what does null represent in the done() function. It seems to be the first parameter always and I am confused about what is actually does?

    • what is the null parameter again in cb(null, user);

按照惯例,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 有其身份验证过程的约定,正如他们的文档所说:

If the credentials are valid, the verify callback invokes done to supply Passport with the user that authenticated. If the credentials are not valid (for example, if the password is incorrect), done should be invoked with false instead of a user to indicate an authentication failure.

这就是你在这里所做的:

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. What does serialize and deserialize do? Does serialize get called after a login when session is stored in the browser? and deserialize is when a page is accessed so the session is deserialized on the server to validate that user?

嗯,Passport 的文档说:

If authentication succeeds, a session will be established and maintained via a cookie set in the user's browser. Each subsequent request will not contain credentials, but rather the unique cookie that identifies the session. In order to support login sessions, Passport will serialize and deserialize user instances to and from the session.

这意味着,在用户登录后,会调用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(而不是整个用户对象)传递给 serializeUser 中的 cb,以保持会话中存储的数据量较小。当进一步的请求发生时,这个 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);
  });
});