Bcrypt compare方法始终返回false,请求排查代码问题
Bcrypt Compare始终返回false的问题排查与修复
问题1:注册表单重复的name属性导致密码被错误处理
注册视图中,密码输入框和确认密码输入框的name属性都设置为password,这会导致表单提交时,req.body.password是一个包含两个值的数组(比如用户输入1234两次,req.body.password就是["1234", "1234"])。而你在加密时调用了password.toString(),最终加密的是"1234,1234"这个字符串,和登录时用户输入的单个密码自然无法匹配。
修复方案:
修改注册视图的确认密码输入框name属性,改为confirmPassword:
<div class="form-group"> <input type="password" name="confirmPassword" class="form-control" id="confirmPassword" placeholder="Confirm Password"> </div>
同时在server.js的注册接口中,增加密码一致性校验(可选但推荐):
server.post('/registration', async(req, res) => { const { firstName, lastName, email, password, confirmPassword } = req.body // 新增密码一致性校验 if (password !== confirmPassword) { return res.render('registration.ejs', { messages: { error: '两次输入的密码不一致' } }) } await bcrypt.hash(password.toString(), salt) .then((hashedPassword) => { users.push({ id: Date.now().toString(), email: email, password: hashedPassword, firstName: firstName, lastName: lastName }) console.log(users) res.redirect("/login") }) .catch((error) => { console.log(error); res.render('registration.ejs', { messages: { error: '注册失败,请重试' } }) }); })
问题2:Passport认证函数未调用done回调
在passport.js的authenticateUsers函数中,调用bcrypt.compare后,无论对比结果是成功还是失败,都没有调用Passport要求的done回调函数。这会导致Passport无法获取认证结果,即使密码对比成功,也无法完成登录流程,同时你看到的compare返回false可能是因为之前的密码错误,而这个问题会进一步导致认证逻辑完全失效。
修复方案:
修改passport.js中的authenticateUsers函数,在bcrypt.compare的回调中调用done:
const authenticateUsers = async(email, password, done) => { const user = await getUserByEmail(email) console.log("THE Password BEFORE COMPARISON ---> " + password) console.log(user) if (user == null) { console.log("user null;;;lllll") return done(null, false, { message: "用户未注册" }) } bcrypt.compare(password.toString().trim(), user.password, function(err, result) { console.log("THE PASSWORD AFTER COMPARISON ---> " + password) console.log(user) if (err) { console.log(err) return done(err) // 传递错误给Passport } if (result) { console.log("PASSWORD MATCHES") return done(null, user) // 认证成功,传递用户信息 } else { console.log("DOESNOT MATCH") return done(null, false, { message: "密码错误" }) // 认证失败,返回错误信息 } }) }
额外优化建议
- 避免全局固定salt:
bcrypt.hash可以自动生成salt,不需要手动调用bcrypt.genSaltSync,直接使用await bcrypt.hash(password, 10)即可,更安全。 - 处理
getUserByEmail的异步逻辑:虽然当前users是内存数组,find是同步方法,但如果后续改用数据库,建议保持异步风格,确保代码可扩展。
内容的提问来源于stack exchange,提问作者Sami
相关产品推荐
相关产品推荐

