Bcrypt compare()始终返回false,登录验证失败求助
密码比对失败导致登录返回「无效凭证」问题
我用以下代码实现用户密码的加密存储和比对逻辑,但登录函数始终返回「无效凭证」错误,经日志排查,问题出在密码比对环节。
密码加密与比对的Schema代码
UserSchema.pre('save', async function() { const salt = await bcrypt.genSalt(10) this.password = await bcrypt.hash(this.password, salt) }) UserSchema.methods.comparePassword = async function(candidatePassword) { const isMatch = await bcrypt.compare(candidatePassword, this.password) console.log(this.password); console.log(candidatePassword); return isMatch }
登录函数代码
const login = async(req, res) => { const { email, password } = req.body if (!email || !password) { throw new CustomError.BadRequestError('Please provide email and password') } const user = await User.findOne({ email }) if (!user) { throw new CustomError.UnauthenticatedError('Invalid Credentials') } const isPasswordCorrect = await user.comparePassword(password) if (!isPasswordCorrect) { throw new CustomError.UnauthenticatedError('Invalid Credentials') } if (!user.isVerified) { throw new CustomError.UnauthenticatedError('Please Verify Your Email ') } const tokenUSer = createTokenUser(user) attachCookiesToResponse({ res, user: tokenUSer }) res.status(StatusCodes.OK).json({ user: tokenUSer }) }
排查与解决方向
- 避免密码重复加密:当前的
pre('save')钩子会在每次保存用户时都执行加密,包括用户更新其他字段(如验证状态、邮箱)的时候,这会导致密码被多次加密,最终比对失败。修改钩子,仅在密码字段被修改时执行加密:UserSchema.pre('save', async function() { // 仅当密码字段被修改时才加密 if (!this.isModified('password')) return; const salt = await bcrypt.genSalt(10) this.password = await bcrypt.hash(this.password, salt) }) - 检查注册时的密码处理:确认用户注册/创建时传入的是明文密码,没有提前手动加密,否则经过钩子二次加密后,比对必然不匹配。
- 验证数据库存储的密码:查看数据库中的用户文档,确认
password字段是bcrypt加密后的格式(通常以$2b$开头的字符串),而非明文或异常值。 - 核对compare参数顺序:虽然代码中
bcrypt.compare(candidatePassword, this.password)的参数顺序正确(明文在前,加密密码在后),但可通过日志输出确认:this.password应为加密字符串,candidatePassword应为用户输入的明文密码,若顺序颠倒也会导致比对失败。
内容的提问来源于stack exchange,提问作者SAMBHAV
相关产品推荐
相关产品推荐

