Passport.js:LocalStrategy 如何访问用户信息?

Posted

技术标签:

【中文标题】Passport.js:LocalStrategy 如何访问用户信息?【英文标题】:Passport.js: How does LocalStrategy accesses the user information? 【发布时间】:2020-05-14 04:14:20 【问题描述】:

我已经阅读了几篇解释护照身份验证流程的文章并理解了大部分概念。但是,仍有一些模糊的地方需要解释,以便我可以一劳永逸地了解 Passport。 让我们看看这个实现用户注册的简单示例:

passport.js

passport.use(
  'register',
  new LocalStrategy(
    
      usernameField: 'username',
      passwordField: 'password',
      passReqToCallback: true,
      session: false,
    ,
    (req, username, password, done) => 
      // TODO:Why is req.body.email is used and not req.body.username
      // And how are these values passed to register in the first place?
      console.log(username);
      console.log(req.body.email);

      try 
        User.findOne(
          where: 
            [Op.or]: [
              
                username,
              ,
               email: req.body.email ,
            ],
          ,
        ).then(user => 
          if (user != null) 
            console.log('username or email already taken');
            return done(null, false, 
              message: 'username or email already taken',
            );
          
          /**
           * on register the user’s password is hashed and salted with the encryption package bcrypt
           * 
           */
          bcrypt.hash(password, BCRYPT_SALT_ROUNDS).then(hashedPassword => 
            User.create(
              username,
              password: hashedPassword,
              email: req.body.email,
            ).then(user => 
              console.log('user created');
              return done(null, user);
            );
          );
        );
       catch (err) 
        //In case of an Error interacting with our database, we need to invoke done(err)
        //Calling done will make the flow jump back into passport.authenticate. 
        //It's passed the error, user and additional info object (if defined).
        return done(err);
      
    ,
  ),
);

registerUser.js:

app.post('/registerUser', (req, res, next) => 
    //Calling done will make the flow jump back into passport.authenticate. 
    //It's passed the error, user and additional info object (if defined).

    passport.authenticate('register', (err, user, info) => 
      if (err) 
        console.error(err);
      
      if (info !== undefined) 
        console.error(info.message);
        res.status(403).send(info.message);
       else 
        // eslint-disable-next-line no-unused-vars
        req.logIn(user, error => 
          console.log(user);
          const data = 
            first_name: req.body.first_name,
            last_name: req.body.last_name,
            email: req.body.email,
            username: user.username,
          ;
          console.log(data);
          User.findOne(
            where: 
              username: data.username,
            ,
          ).then(user => 
            console.log(user);
            user
              .update(
                first_name: data.first_name,
                last_name: data.last_name,
                email: data.email,
              )
              .then(() => 
                console.log('user created in db');
                res.status(200).send( message: 'user created' );
              );
          );
        );
      
    )(req, res, next);
  );

问题 1:我看不到 LocalStrategy 中的代码在知道 Passport.authenticate 已被调用后如何访问用户信息以这种方式:

    app.post('/registerUser', (req, res, next) => 
passport.authenticate('register', (err, user, info) => 

那么**regiser LocalStrategy**里面的代码是如何访问用户名、邮箱和密码的:

(req, username, password, done) => 
  console.log(username);
  console.log(req.body.email);  

问题 2:LocalStrategy 中的 username 怎么会被直接称为 username(密码也是一样的)和电子邮件由 req.body.email 调用?

 console.log(username);
  console.log(req.body.email); 

这里:

User.create(
              username,
              password: hashedPassword,
              email: req.body.email,
            )

问题3:如果注册LocalStrategy中已经创建了用户,为什么还需要更新请求回调中的用户信息?强>:

registerUser.js

  .update(
                first_name: data.first_name,
                last_name: data.last_name,
                email: data.email,
              )

passport.js

User.create(
              username,
              password: hashedPassword,
              email: req.body.email,
            )

EDIT 1问题4(req, res, next);在末尾的作用是什么POST 回调?

【问题讨论】:

【参考方案1】:

问题 1&2: 答案在于传递的对象 LocalStrategy

   
      usernameField: 'username',
      passwordField: 'password',
      passReqToCallback: true,
      session: false,
      

属性passReqToCallbackreq将作为第一个参数传递给验证回调:

(req, username, password, done) =>   

但是,仍然不清楚用户名和密码是如何传递给这个函数的。为什么在这个对象中以这种方式定义它们:

 usernameField: 'username',
 passwordField: 'password', 

难道不应该像电子邮件一样通过 req.body.username 访问它们吗:

User.findOne(
          where: 
            [Op.or]: [
              
                username,
              ,
               email: req.body.email ,
            ],
          ,   

问题 3:这是我找到的解释:

我也可以将这些额外的数据传递给中间件, 但我希望 Passport 只处理身份验证,而不是用户创建 也是。模块化,记住。

另外,如果要将身份验证拆分为单独的 使用仅包含加密用户名的单独数据库的服务和 密码,这样操作起来更容易,然后使用用户名 或ID在此查找并更新对应的用户记录 注册服务。

【讨论】:

【参考方案2】:

对于问题1:当你调用passport.authenticate('register')时,你应该传递reqres,然后是next,以便passport.use(localStrategy)获取用户信息。

对于问题 2,用户名从 localstrategy 内部的 req 对象中获取

对于问题3:您不需要更新用户信息。相反,您可以像您一样直接将资源发送给.then()函数中的用户:

then(() => 
  console.log('user created in db');
  res.status(200).send(
    message: 'user created'
  );
);

【讨论】:

所以 (req, res, next) 在 POST 请求结束时将这些参数传递给 passport.js 中的注册代码?如果是这样,我看不出语法如何使它起作用。我应该学习或重新学习 POST 请求的语法吗? 所以 (req, res, next) 在 POST 请求结束时将这些参数传递给 passport.js 中的注册代码?是的

以上是关于Passport.js:LocalStrategy 如何访问用户信息?的主要内容,如果未能解决你的问题,请参考以下文章

在集成测试中模拟不同的 passport.js 策略

Passport.js 身份验证失败时发回 JSON 响应

Sequelize - findOne().success() 未定义

如何在 passport-facebook / Passport.js 中捕获 FacebookAuthorizationError?

Passport.js:passport-facebook-token 策略,通过 JS SDK 登录然后验证护照?

passport.js 是不是支持 ajax?