我正在执行身份验证功能。它实际上适用于硬编码用户,但是当我开始从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
};
}
})
})
})
}
控制台日志记录似乎证实了这一承诺。老实说,我复制粘贴了很多内部代码,因此我仍然不确定它是如何工作的,但是promise语法至少是我有信心的。用户从Firebase中拉出并检查用户名和密码是否匹配,if (result)
的勇气应该运行。 result
确实以true
的形式返回,这与我尝试使用的登录名是正确的,但是我的密码表拒绝了我,因为它会在认证方法完成之前继续进行处理。
在另一个Javascript文件中,我有调用该文件的方法。
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,我认为是具有异步性的问题。谁能解释为什么外部身份验证功能没有等待,我该如何做呢?
答案 0 :(得分:0)
有两个可能的问题:
forEach函数返回未定义,请参见Array.prototype.forEach()。如果需要迭代结果,则可以使用Array.prototype.map()
以下语句听起来像代码未正确等待结果:
我的密码表拒绝了我,因为它在身份验证方法完成之前会继续处理。
如果您具有JavaScript承诺,则只有在承诺被解决或拒绝的情况下,才能使用await
关键字来继续执行函数。在这里查看示例:https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Operators/await
在您的示例中,authenticate函数如下所示:
async function authenticate(req, res, next) {
console.log(req.body);
await userService.authenticate(req.body)
.then(...)
.catch(...);
}
请注意async
和await
关键字。这样,它只有在userService.authenticate(..)
调用得到完全处理之后才返回。
答案 1 :(得分:0)
Firebase QuerySnapshot
具有类型docs
的{{1}}属性。您可以使用它和Array.find
来搜索用户。搜索用户时,还应Array<QueryDocumentSnapshot<T>>
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
}
}
}
})
}
和usersname
哈希。 Firebase具有您应该使用的非常可靠的身份验证系统。