使用bcrypt登录失败,compare始终返回false求助排查
解决登录时bcrypt验证失败返回"Invalid login credentials"的问题
从你提供的注册和登录代码来看,注册功能正常但登录时密码比对失败,核心问题肯定出在bcrypt的密码哈希存储或比对环节,下面是几个最常见的排查方向和解决方法:
检查User模型中password字段的长度限制
bcrypt生成的哈希值固定是60个字符长度,如果你的User Schema里password字段的长度设置小于60(比如设成了varchar(50)或者mongoose里的maxlength:50),存储时哈希值会被截断,自然比对失败。你需要确保字段长度足够,比如mongoose Schema可以这么定义:const userSchema = new mongoose.Schema({ firstName: String, lastName: String, email: String, password: { type: String, required: true, minlength: 60, maxlength: 60 } });要是用的是SQL数据库,也要对应把password字段的长度设为至少60。
验证注册时的哈希值是否完整存储
你可以在注册成功后直接查看数据库里的用户记录,确认password字段是完整的60位哈希字符串(格式一般是$2a$10$开头)。也可以在注册控制器里加个日志,输出生成的哈希值,确认没出问题:signup: function (req, res) { console.log(req.body) const hashedPassword = bcrypt.hashSync(req.body.password, 10); console.log('生成的密码哈希:', hashedPassword); // 检查是否是60位的有效哈希 var user = new User({ firstName: req.body.firstName, lastName: req.body.lastName, password: hashedPassword, email: req.body.email }); user.save(function(err, result) { if (err) { return res.status(500).json({ title: 'An error occurred', error: err }); } res.status(201).json({ message: 'User created', obj: result }); }); }确认登录时传入的密码没有异常
有时候前端传入的密码可能带了前后空格,或者转义字符导致和用户实际输入不一致。你可以在登录控制器里先打印传入的密码,确认内容正确:User.findOne({ email: req.body.email }, function (err, user) { if (err) { return res.status(500).json({ title: 'An error occurred', error: err }); } if (!user) { return res.status(401).json({ title: 'Login failed', error: { message: 'Invalid login credentials' } }); } console.log('前端传入的密码:', req.body.password); console.log('数据库存储的哈希:', user.password); if (!bcrypt.compareSync(req.body.password, user.password)) { return res.status(401).json({ title: 'Login failed', error: { message: 'Invalid login credentials' } }); } // ...后续逻辑 })检查bcrypt版本兼容性
不同版本的bcrypt可能存在哈希格式的细微差异,虽然compareSync一般会兼容旧格式,但如果你的项目里注册和登录环节用的bcrypt版本不一致,也可能导致比对失败。可以统一安装最新版本的bcrypt:npm uninstall bcrypt npm install bcrypt@latest
一般来说,字段长度不够导致哈希被截断是这个问题最常见的原因,建议你先从这个方向排查。
内容的提问来源于stack exchange,提问作者Miran Parkar
相关产品推荐
相关产品推荐

