【问题标题】:Auth using passport.js confusion with syntax?使用 passport.js 进行身份验证与语法混淆?
【发布时间】:2016-05-30 02:28:39
【问题描述】:

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

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

最后null参数又是什么cb(null, user);

【问题讨论】:

  • nodejs 中有一个约定,可以在回调的第一个参数中传递任何错误。你会在几乎每个节点库中看到这一点,包括像fs 这样的内置模块。所以传递null 就像是在将结果提供给回调之前,函数内部没有发生错误。

标签: javascript node.js express passport.js


【解决方案1】:
  1. 在 done() 函数中 null 代表什么。它似乎总是第一个参数,我对实际做什么感到困惑?

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

按照惯例,NodeJS 使用 error-first 回调,这意味着回调函数的第一个参数始终是错误对象。如果没有任何错误,则传入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. 序列化和反序列化有什么作用?当会话存储在浏览器中时,是否会在登录后调用序列化?而反序列化是在访问页面时在服务器上反序列化会话以验证该用户?

嗯,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,而不是整个用户对象传递给 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);
  });
});

【讨论】:

    猜你喜欢
    • 2023-04-03
    • 2018-05-03
    • 2023-04-05
    • 2020-01-02
    • 2022-08-13
    • 1970-01-01
    • 2013-09-25
    • 2018-01-17
    • 2013-06-26
    相关资源
    最近更新 更多