Функция аутентификации не ждет обещания для разрешения - PullRequest
0 голосов
/ 01 апреля 2020

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

У меня тут какая-то скучная функция Javascript, которую я верю возвращает обещание.

function authenticate({ username, password }) {
    return users.then((querySnapshot) => {
        return querySnapshot.forEach(doc => {
            let user = doc.data();
            if (user.username.toUpperCase() == username.toUpperCase())
                return bcrypt.compare(password, user.password).then(function (result) {
                    console.log(password);
                    console.log(user.password);
                    console.log(result);
                    if (result) {
                        const token = jwt.sign({ sub: user.id }, config.secret);
                        const { password, ...userWithoutPassword } = user;
                        return {
                            ...userWithoutPassword,
                            token
                        };
                    }
                })
        })
    })
}

Кажется, что консольное журналирование подтверждает, что это обещание. Честно говоря, я скопировал большую часть кода внутри, так что я до сих пор не совсем уверен, как он работает, но синтаксис обещаний - это, по крайней мере, то, в чем я уверен. После того, как я go через список пользователей, извлеченных из Firebase, и убедитесь, что имя пользователя и пароль совпадают, кишки if (result) должны работать. result возвращается как true, что является правильным для того, с чем я пытаюсь войти, но моя форма пароля отклоняет меня, потому что она продолжает обработку до завершения метода authenticate.

В другом Javascript file, у меня есть метод, который вызывает этот метод.

function authenticate(req, res, next) {
    console.log(req.body);
    userService.authenticate(req.body)
        .then(user => console.log(user))
        //.then(user => user ? res.json(user) : res.status(400).json({ message: 'Username or password is incorrect' }))
        .catch(err => next(err));
}

В последнее время я много узнаю об асинхронном программировании, но это немного противоречит моим ожиданиям. Конечно, выполнение .then() на authenticate() должно запустить authenticate(), получить обещание, даже если оно не решено, а затем дождаться его разрешения, прежде чем выполнять остальные операторы? В настоящее время проблема заключается в том, что метод работает, не находит значения для user, а затем выбрасывает 400, что, как мне кажется, является проблемой с асинхронностью. Может кто-нибудь объяснить, почему внешняя функция аутентификации не ждет и как я могу заставить это сделать это?

Ответы [ 2 ]

0 голосов
/ 01 апреля 2020

Firebase QuerySnapshot имеет свойство docs типа Array<QueryDocumentSnapshot<T>>. Вы можете использовать это и Array.find для поиска пользователя. Вы также должны await для bcrypt.compare при поиске пользователя.

function authenticate({ username, password }) {
    return users.then(async (querySnapshot) => {
        const { usersDocs: docs } = querySnapshot;
        const userDoc = usersDocs.find(doc => {
          return doc.data().username === username;
        });

        if (userDoc) {
            let user = doc.data();
            const pwdCompareResult = await bcrypt.compare(password, user.password);

            console.log(password);
            console.log(user.password);
            console.log(pwdCompareResult );

            if (pwdCompareResult ) {
                const token = jwt.sign({ sub: user.id }, config.secret);
                const { password, ...userWithoutPassword } = user;
                return {
                    ...userWithoutPassword,
                    token
                }
            }
        }
    })
}

Пожалуйста, используйте вместо этого проверку подлинности Firebase

Ваша реализация аутентификации не надежна, и она передает конфиденциальные данные каждому пользовательские устройства, такие как usersname и password хэши. Firebase имеет очень solid систему аутентификации, которую вы должны использовать.

0 голосов
/ 01 апреля 2020

Возможны две проблемы:

Результат forEach

Функция forEach возвращает неопределенное значение, см. Array.prototype.forEach () . Если вам нужен результат итерации, вы можете использовать Array.prototype.map ()

Ожидание обещания

Следующее утверждение звучит так, как будто код не ожидайте результата должным образом:

моя форма пароля отклоняет меня, потому что она продолжает обрабатываться до завершения метода аутентификации.

Если у вас есть обещание javascript, вы можете используйте ключевое слово await, чтобы продолжить выполнение функции, только если обещание либо разрешено, либо отклонено. Посмотрите на примеры здесь: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Operators/await

В вашем примере функция аутентификации будет выглядеть следующим образом:

async function authenticate(req, res, next) {
  console.log(req.body);
  await userService.authenticate(req.body)
    .then(...)
    .catch(...);
}

Обратите внимание на async и await ключевых слов. Таким образом, он возвращается только после полной обработки вызова userService.authenticate(..).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...