使用NodeJS比对MySQL存储的哈希密码时无法正常登录求助
以下是某系统登录功能的代码片段,该功能要求用户输入邮箱和密码完成系统登录,即便输入的账号信息正确,代码也始终报错“邮箱或密码不正确”。我使用的技术栈为NodeJS和MySQL数据库,恳请帮忙排查问题!
问题排查
核心错误点
- 执行顺序错误:在判断数据库查询错误、判断查询结果是否存在之前,就直接访问
results[0].password,如果邮箱不存在/数据库查询报错,results[0]为undefined,读取password属性直接抛出异常,后续校验逻辑无法正常执行 - 空结果判断逻辑错误:MySQL查询无匹配数据时返回空数组而非null,空数组的布尔值为
true,!results判断永远为假,无法命中无匹配用户的分支 - 冗余查询:同一邮箱重复执行两次查询,完全可以复用第一次的查询结果
- 变量未声明:
sess、patientSess未用const/let声明,属于隐式全局变量,可能引发不可预知的作用域问题
修复后代码
exports.afterLogin = async (req, res) => { try { const { email, password } = req.body; db.query('Select * FROM patient WHERE email= ?', [email], async (error, results) => { // 先判断查询错误 if (error) { console.log(error); return res.status(500).render('patientLogin', { message: '服务器内部错误', messageClass: 'alert-danger' }); } // 再判断是否存在匹配用户 if (!results.length) { return res.status(400).render('patientLogin', { message: 'Email or password is incorrect!', messageClass: 'alert-warning' }); } // 最后校验密码 const verified = bcrypt.compareSync(password, results[0].password); if (!verified) { return res.status(400).render('patientLogin', { message: 'Email or password is incorrect!', messageClass: 'alert-warning' }); } // 复用第一次查询结果,无需二次查询 const sess = req.session; sess.patient = {}; sess.patient.city = results[0].city; sess.patient.name = results[0].first_name; sess.patient.ids = results[0].patient_id; const patientSess = Object.assign({}, sess.patient); const id = results[0].id; const token = jwt.sign({ id }, process.env.JWT_SECRET, { expiresIn: process.env.JWT_EXPIRES_IN }); console.log("Token is: " + token); const cookieOptions = { expires: new Date( Date.now() + process.env.JWT_COOKIE_EXPIRES * 24 * 60 * 60 * 1000 ), httpOnly: true } res.cookie('jwt', token, cookieOptions); res.status(200).redirect("/searchDoctor"); }) } catch (error) { console.log(error); res.status(500).render('patientLogin', { message: '服务器内部错误', messageClass: 'alert-danger' }); } }
优化建议
- 推荐使用
bcrypt.compare异步方法替代同步方法,避免阻塞NodeJS事件循环 - 可以将回调式的
db.query封装为Promise,结合async/await使用,避免回调嵌套,代码逻辑更清晰
内容的提问来源于stack exchange,提问作者Rudransh J
相关产品推荐
相关产品推荐

