简体   繁体   English

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

[英]Passport.js: How does LocalStrategy accesses the user information?

I have read several articles explaining how the passport authentication flows and understood most of the concepts.我已经阅读了几篇文章,解释了护照身份验证的流程并理解了大部分概念。 However, there are still a couple of vague points to be explained so that I can wrap my head around Passport once and for all.但是,仍然有一些模糊的点需要解释,以便我可以一劳永逸地围绕 Passport。
Let's see this simple example that implements user registration :让我们看看这个实现用户注册的简单示例:

passport.js护照.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:注册用户.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);
  });

Question 1: I do not see how the code inside LocalStrategy has access to the user information knowing that Passport.authenticate has been called in this manner:问题 1:我不知道LocalStrategy内部的代码如何在知道Passport.authenticate已以这种方式调用的情况下访问用户信息:

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

So how does the code inside **regiser LocalStrategy ** accesses the username,email and password:那么**regiser LocalStrategy **里面的代码是如何访问用户名、邮箱和密码的:

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

Question2: How come username inside LocalStrategy is called username directly (the same thing for password) and email is called by req.body.email ?问题2:如何进来LocalStrategy用户名叫做着用户名(密码同样的事情)和电子邮件是由req.body.email叫什么名字?

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

and here:和这里:

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

Question 3: Why is there a need to update the user information in the request callback if the user has already been created in the register LocalStrategy :问题三:如果在注册 LocalStrategy 中已经创建了用户,为什么还需要在请求回调中更新用户信息:

registerUser.js注册用户.js

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

passport.js护照.js

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

EDIT 1编辑 1
Question 4: What is the role of (req, res, next);问题4: (req, res, next)的作用是什么 at the end of the POST callback?POST回调结束时?

For question 1: when you are calling passport.authenticate('register') you should pass req , res , and next at then end, so that passport.use(localStrategy) gets the user information.对于问题 1:当您调用passport.authenticate('register')您应该通过reqres和 next 然后结束,以便passport.use(localStrategy)获取用户信息。

For question 2, username getting from the req object inside localstrategy对于问题 2,用户名从localstrategyreq对象localstrategy

For question 3: You don't need to update the user info.instead you can directly send the res to user in .then() function as you did:对于问题 3:您不需要更新用户信息。相反,您可以像您一样直接在.then()函数中将 res 发送给用户:

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

Question 1&2: The answer lies within the object that is passed LocalStrategy :问题 1&2:答案在传递LocalStrategy的对象中:

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

The attribute passReqToCallback , the req will be passed as the first argument to the verify callback:属性passReqToCallbackreq将作为第一个参数传递给验证回调:

(req, username, password, done) => {}  

However, what is still not clear is how the username and password are passed to this function.但是,仍然不清楚的是用户名和密码是如何传递给这个函数的。 Why are they defined in this manner in this object:为什么在这个对象中以这种方式定义它们:

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

Shouldn't they be accessed through req.body.username just like the email:他们不应该像电子邮件一样通过 req.body.username 访问:

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

Question 3: Here's an explanation I found:问题 3:这是我找到的解释:

I could have passed this extra data through to the middleware as well, but I want Passport to only handle authentication, not user creation as well.我也可以将这些额外的数据传递给中间件,但我希望 Passport 只处理身份验证,而不是用户创建。 Modularization, remember.模块化,记住。

Plus, if the authentication were to be split out into a separate service with a separate database of just encrypted usernames and passwords, this would make it easier to do so, then use the username or ID to find and update the corresponding user record in this registration service.另外,如果将身份验证拆分为单独的服务,并使用单独的仅加密用户名和密码的数据库,这将更容易做到这一点,然后使用用户名或 ID 在此查找和更新相应的用户记录注册服务。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM