Паспорт. js: Как LocalStrategy получает доступ к пользовательской информации? - PullRequest
5 голосов
/ 28 января 2020

Я прочитал несколько статей, объясняющих, как проходит проверка подлинности паспорта, и понял большинство концепций. Тем не менее, есть еще пара неясных моментов, которые нужно объяснить, чтобы я мог раз и навсегда обернуть паспорт.
Давайте посмотрим на этот простой пример, который реализует регистрация пользователей :

паспорт. 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 напрямую (то же самое для пароля), а электронная почта вызывается req.body.email ?

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

и здесь:

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

Вопрос 3: Почему необходимо обновить информацию пользователя в * 1 046 * обратный вызов , если пользователь уже был создан в регистре LocalStrategy :

registerUser. js

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

паспорт. js

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

РЕДАКТИРОВАТЬ 1
Вопрос 4: Какова роль ( req, res, next); в конце обратного вызова POST ?

Ответы [ 2 ]

0 голосов
/ 29 января 2020

Вопрос 1 и 2: Ответ находится в пределах объекта, который передается LocalStrategy :

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

Атрибут passReqToCallback , req будет передано в качестве первого аргумента для обратного вызова проверки:

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

Однако все еще неясно, как имя пользователя и пароль передаются этой функции. Почему они определены следующим образом в этом объекте:

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

Разве они не должны быть доступны через req.body.username так же, как электронная почта:

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

Вопрос 3: Вот объяснение, которое я нашел:

Я мог бы также передать эти дополнительные данные в промежуточное ПО, но я хочу, чтобы Passport обрабатывал только аутентификацию, а не создание пользователей. Модуляризация, помните.

Плюс, если аутентификация должна была быть разделена на отдельный сервис с отдельной базой данных только зашифрованных имен пользователей и паролей, это упростило бы это, затем используйте имя пользователя или идентификатор найти и обновить соответствующую запись пользователя в этой службе регистрации.

0 голосов
/ 28 января 2020

Для вопроса 1: когда вы звоните passport.authenticate('register'), вы должны передать req, res и затем в конце, чтобы passport.use(localStrategy) получил информацию о пользователе.

Для вопроса 2 , имя пользователя, полученное из объекта req внутри localstrategy

Для вопроса 3: Вам не нужно обновлять информацию пользователя info.instead, вы можете напрямую отправлять res пользователю в функции .then(), как вы сделал:

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