bcrypt.compare始终返回false的登录功能故障排查求助
搞定bcrypt.compare一直返回false的坑
兄弟,从你说的情况——数据库里存的"哈希密码"居然和明文完全一样——就知道问题出在哪了:注册的时候密码根本没被正确哈希,数据库里存的就是明文!这时候用bcrypt.compare去对比明文和"假哈希"(其实是另一个明文),肯定返回false啊。
我给你一步步捋排查和解决方法:
先确认哈希值到底有没有生成
先在你的registerUser函数里加两行日志,看看bcrypt.hash到底输出了啥:
const registerUser = async (request, response) => { console.log('用户输入的明文密码:', request.body.password); const hashedPassword = await bcrypt.hash(request.body.password, 12); console.log('bcrypt生成的哈希值:', hashedPassword); // 正常应该是$2b$12开头的60位左右字符串 const user = new UserModel({ username: request.body.username, password: hashedPassword }); // ... 后面的代码不变 };
如果输出的hashedPassword和明文一模一样,那说明bcrypt的哈希方法没干活,大概率是依赖的问题:
- 先卸载重装bcrypt试试:
npm uninstall bcrypt npm install bcrypt - 要是你用的Windows系统,可能缺编译环境,先装个
windows-build-tools再重装bcrypt:npm install --global windows-build-tools npm install bcrypt
检查你的UserModel定义
要是哈希值确实生成了,但存进数据库就变成明文了,那肯定是Mongoose Schema(假设你用的Mongoose)的密码字段有问题:
- 有没有不小心加了
set钩子,把哈希值又转成明文了? - 字段类型是不是设错了?密码字段就老老实实设成
String就行,别瞎加什么trim或者其他奇怪的约束(虽然trim一般不会搞砸,但保险起见先去掉)。
给你个正确的Schema示例参考:
const userSchema = new mongoose.Schema({ username: { type: String, required: true, unique: true }, password: { type: String, required: true } });
直接去数据库看一眼
手动去数据库里查一下用户的password字段,正常的bcrypt哈希值是$2b$12$开头的,长度固定60位左右。要是你看到的是明文密码,那前面两步肯定有一步没做好。
最后排查登录环节的小细节
- 确认登录时的
request.body.password没被中间件篡改(比如某个中间件自动做了trim?比如用户输入密码带空格,trim后和数据库里的明文不一样?),在login函数里加个日志确认:const login = async (request, response) => { try{ console.log('登录提交的密码:', request.body.password); const user = await UserModel.findOne({username: request.body.username}) // ... 后续代码 } catch(error){ response.status(500).send({message: error.message}); } } - 另外,别混用
bcrypt和bcryptjs!这俩API虽然像,但哈希算法细节不一样,用A哈希的密码,用B去对比肯定失败。
按这个流程走,绝对能解决问题——99%的概率就是注册时哈希没生成,或者Schema把哈希值搞成明文存了。
内容的提问来源于stack exchange,提问作者elmgren
相关产品推荐
相关产品推荐

