You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NodeJS中Bcrypt报错Error: Illegal callback: string的解决求助

修改密码API错误解决方案

错误根源

bcrypt.compare的参数传递错误:该方法的正确参数格式为(明文密码, 已加密密码, 回调函数),你额外传入了salt参数,导致方法把字符串类型的salt误认为是回调函数,直接触发Illegal callback: string错误。

其他隐藏问题

  • User.findByPk是异步方法,直接赋值得到的是Promise对象,不是实际用户实例,后续if (!user)判断永远不成立,且user.password会返回undefined。
  • 响应语句res.status(200).send放在异步回调外部,会导致不管密码验证是否成功,都会提前返回成功响应,异步逻辑还未执行完就结束请求。
  • user.set方法中的where参数多余,操作已查询到的用户实例时无需指定查询条件。
  • 异步回调内的错误无法被外层try/catch捕获,因为回调函数属于独立执行上下文。

修复后的完整代码

exports.changePassword = async (req, res) => {
  try {
    // 异步获取实际用户实例
    const user = await User.findByPk(req.params.user_id);
    const body = req.body;
    
    if (!user) {
      return res.status(400).send("无效的用户ID");
    }
    
    // 调用bcrypt.compare时移除多余的salt参数,改用async/await简化逻辑
    const isMatch = await bcrypt.compare(body.password, user.password);
    if (!isMatch) {
      return res.status(400).send("密码不匹配!");
    }
    
    // 生成新密码哈希值
    const salt = bcrypt.genSaltSync(10);
    const newPassword = bcrypt.hashSync(body.newPassword, salt);
    
    // 更新用户属性,无需where参数
    user.set({ 
      password: newPassword, 
      updated_at: now() 
    });
    await user.save();
    
    // 操作成功后再返回响应
    res.status(200).send("密码修改成功!");
  } catch (error) {
    res.status(500).send("发生错误");
    console.log(error);
  }
};

关键修改说明

  1. 将控制器函数改为async,用await获取User.findByPk的结果,确保拿到实际用户实例。
  2. 移除bcrypt.compare的salt参数,改用async/await替代回调写法,让错误能被外层try/catch捕获。
  3. 将响应语句移到密码验证通过、用户保存完成之后,保证只有操作成功才返回成功信息。
  4. 删除user.set中的where选项,直接修改已查询到的用户实例属性即可。

内容的提问来源于stack exchange,提问作者KAITO_NGUYEN 2KXXX

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 02:35:19