使用Passport与Mongoose时,pre-save中间件未存储哈希密码
解决Mongoose Pre-Save中间件密码哈希不生效的问题
我一眼就揪出问题所在了——你在pre('save')中间件里用了箭头函数,这直接导致this的指向完全不对!
箭头函数不会绑定自己的this,它会继承外层作用域的this,而不是指向当前要保存的Mongoose文档对象。所以你的let user = this;拿到的根本不是目标用户实例,自然没法正确获取user.password来做哈希处理。
修正方案:
- 把箭头函数换成普通函数,让
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流程 }); }); });
额外优化点:加入
user.isModified('password')判断。这样只有当密码字段被修改(或者是新创建的用户)时才会触发哈希操作,避免用户更新其他字段(比如昵称、邮箱)时,密码被不必要地重新哈希。完善错误处理:哈希过程中出现错误时,一定要调用
next(err),否则Mongoose的save流程会一直挂起,无法正确捕获和处理异常。
验证方式:
修改代码后,尝试创建新用户或更新现有用户的密码,然后查看数据库中的password字段,应该已经变成哈希后的字符串,而非明文。同时控制台会打印出Pre-Save Hash has fired.,说明中间件已正常触发。
内容的提问来源于stack exchange,提问作者Chris Rutherford
相关产品推荐
相关产品推荐

