登录时Bcrypt密码比对始终返回无效 即便输入密码正确
问题定位
你这个代码有个非常典型的低级错误,直接导致所有比对逻辑失效:
- 变量名覆盖:
bcrypt.compare的回调参数你命名成了res,和外层Express的响应对象res重名了。回调里拿到的res只是个表示比对是否通过的布尔值,你在布尔值上调用.status()、.json()方法会直接抛类型错误,代码逻辑完全走歪,最后就落到返回401密码错误的分支。 - 错误分支没加
return:bcrypt运行报错的时候,你返回完错误响应没有终止函数,代码还会继续往下执行后续的比对判断,会出现一次请求返回两次响应的报错。 - 字段名写错了:你解构返回用户信息的时候,要剔除的密码字段写的是
password,但你实际存密码的字段是wachtwoord,就算登录成功,哈希密码也会随接口返回出去,有安全风险。 - 语法错误:返回体里的
new Date().toISOString没加执行括号,你传过去的是函数本身,不是执行后的时间字符串。 - JWT签发没做错误处理:如果jwt签发过程报错,接口会直接挂住,客户端收不到任何响应。
修正后可直接用的代码
bcrypt.compare(req.body.wachtwoord, results[0].wachtwoord, function(err, isMatch) { if (err) { logger.error(err); return res.status(err.status || 500).json(err); } if (isMatch) { logger.info("passwords matched, sending userinfo and valid token."); // 剔除实际存储密码的wachtwoord字段,避免敏感信息泄露 const { wachtwoord, ...userinfo } = results[0]; const payload = { docentID: userinfo.docentID }; logger.debug(payload); jwt.sign( payload, jwtSecretKey, { expiresIn: "25d" }, function(err, token) { if (err) { logger.error("JWT sign failed: ", err); return res.status(500).json({ status: 500, message: "Login failed, please try again later.", datetime: new Date().toISOString() }); } logger.info("User logged in, sending: ", userinfo); return res.status(200).json({ status: 200, result: {...userinfo, token }, }); } ); } else { logger.info("Password invalid"); return res.status(401).json({ status: 401, message: "Password invalid.", datetime: new Date().toISOString(), }); } });
额外排查点
如果改完还是比对失败,去检查你注册存哈希的逻辑:
- 确认存到数据库的bcrypt哈希没有被截断,bcrypt生成的哈希固定60位,数据库字段至少要设为
VARCHAR(60),推荐直接设VARCHAR(255)留冗余。 - 确认存哈希的时候没有做额外的编码转换(比如全角半角转换、多余的转义),否则哈希值变了比对永远不通过。
内容的提问来源于stack exchange,提问作者Sheets
相关产品推荐
相关产品推荐

