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

使用Passport与Mongoose时,pre-save中间件未存储哈希密码

解决Mongoose Pre-Save中间件密码哈希不生效的问题

我一眼就揪出问题所在了——你在pre('save')中间件里用了箭头函数,这直接导致this的指向完全不对!

箭头函数不会绑定自己的this,它会继承外层作用域的this,而不是指向当前要保存的Mongoose文档对象。所以你的let user = this;拿到的根本不是目标用户实例,自然没法正确获取user.password来做哈希处理。

修正方案:

  1. 把箭头函数换成普通函数,让this正确指向当前Mongoose文档:
UserSchema.pre('save', function(next) {
  console.log('Pre-Save Hash has fired.');
  let user = this;

  // 优化:仅当密码字段被修改(或新创建用户)时才执行哈希,避免重复操作
  if (!user.isModified('password')) return next();

  bcrypt.genSalt(10, (err, salt) => {
    if (err) {
      console.error(err);
      return next(err); // 务必把错误传递给next,让Mongoose处理异常
    }
    bcrypt.hash(user.password, salt, (err, hash) => {
      if (err) {
        console.error(err);
        return next(err);
      }
      // 用哈希值替换明文密码
      user.password = hash;
      next(); // 继续执行save流程
    });
  });
});
  1. 额外优化点:加入user.isModified('password')判断。这样只有当密码字段被修改(或者是新创建的用户)时才会触发哈希操作,避免用户更新其他字段(比如昵称、邮箱)时,密码被不必要地重新哈希。

  2. 完善错误处理:哈希过程中出现错误时,一定要调用next(err),否则Mongoose的save流程会一直挂起,无法正确捕获和处理异常。

验证方式:

修改代码后,尝试创建新用户或更新现有用户的密码,然后查看数据库中的password字段,应该已经变成哈希后的字符串,而非明文。同时控制台会打印出Pre-Save Hash has fired.,说明中间件已正常触发。

内容的提问来源于stack exchange,提问作者Chris Rutherford

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:26:08