Node.js Express中使用await后密码Hashing不生效问题咨询
问题根因
你当前调用的是bcrypt的回调风格异步接口,JavaScript不会等待回调函数执行完成,就会直接执行后续的数据库更新、返回响应的逻辑,此时password还是原始未哈希的值,所以入库的密码没有被处理。你遇到的res.json返回了哈希后密码属于偶发情况,只是哈希操作碰巧在响应返回前执行完成,不属于稳定可预期的行为。
解决方案
方案1:改用bcrypt的async/await风格API(推荐,和你现有async路由写法适配)
bcrypt原生支持Promise调用,直接用await等待哈希完成再执行后续逻辑即可:
router.put('/:id', async (req, res, next) => { try { let { mail, password } = req.body; // 直接用await调用genSalt和hash,等待异步操作完成 const salt = await bcrypt.genSalt(saltRounds); const hash = await bcrypt.hash(password, salt); password = hash; const newUser = { mail, password }; await User.findByIdAndUpdate(req.params.id, newUser); res.json({ mensaje: `Updated Password ${password}` }); } catch (err) { // 统一捕获异步错误 next(err); } });
方案2:把后续逻辑移入回调函数(不推荐,容易形成回调地狱)
如果你要继续用回调写法,需要把数据库更新、返回响应的逻辑都放到hash的回调内部,保证哈希完成后再执行后续操作:
router.put('/:id', async (req, res, next) => { let { mail, password } = req.body; bcrypt.genSalt(saltRounds, function (err, salt) { if (err) return next(err); bcrypt.hash(password, salt, async function (err, hash) { if (err) return next(err); password = hash; // 所有用到哈希后password的逻辑都要放在回调内部 const newUser = { mail, password }; await User.findByIdAndUpdate(req.params.id, newUser); res.json({ mensaje: `Updated Password ${password}` }); }); }); });
额外建议
- 哈希密码的逻辑建议封装到用户模型的
pre('save')钩子里面,避免每次写更新/注册接口都要手动处理哈希,减少出错概率 - 响应返回结果里不要带出哈希后的密码,避免泄露敏感信息
内容的提问来源于stack exchange,提问作者Kempis
相关产品推荐
相关产品推荐

