bcrypt.compare参数异常排查:用户创建正常但无法登录
排查Node.js登录时
Illegal arguments: string, undefined报错的问题 从你提供的日志和报错栈来看,这个问题的核心很明确:调用bcrypt.compare时传入的第二个参数hash(也就是user.password)是undefined,导致bcrypt因为收到非法参数(字符串和undefined)而抛出错误。下面我帮你一步步分析原因和解决办法:
可能的原因
- 用户创建时密码哈希未正确存入数据库:注册用户的逻辑里,可能没有将明文密码通过bcrypt哈希后保存到
password字段,或者保存时字段名写错(比如存成了pass而非password),导致查询到的用户对象没有password属性。 - 查询用户时未获取
password字段:如果你的getUserByEmail函数在查询时主动排除了password字段(比如Mongoose中用了select('-password')),就会导致返回的user对象里没有password值,自然传入comparePassword时就是undefined。 - Mongoose Schema定义问题:如果User模型的Schema里没有定义
password字段,或者该字段被设置为不返回,也会导致查询结果中缺失这个属性。
解决办法
1. 检查并修复用户注册逻辑
确保在保存新用户前,正确生成密码哈希并赋值给password字段。示例代码如下:
// 注册用户时的哈希处理 const saltRounds = 10; bcrypt.hash(userPlainPassword, saltRounds, (err, hash) => { if (err) throw err; // 将哈希值赋值给用户对象的password字段 const newUser = new User({ email: userEmail, password: hash, // 其他用户字段... }); newUser.save((err) => { if (err) { // 处理保存错误 } else { // 用户创建成功 } }); });
2. 确保getUserByEmail查询包含password字段
检查你的getUserByEmail实现,如果之前排除了password,要修改为包含该字段:
// 正确的getUserByEmail实现(Mongoose示例) module.exports.getUserByEmail = function(email, callback) { // 默认findOne会返回所有字段,包括password User.findOne({ email: email }, callback); // 如果之前用了select排除,改成下面的写法强制获取password // User.findOne({ email: email }).select('+password').exec(callback); };
3. 临时排查:打印用户对象确认字段
在Passport的回调里添加日志,确认查询到的用户是否真的有password属性:
passport.use(new LocalStrategy({ usernameField: 'email' }, function(email, password, done) { User.getUserByEmail(email, function(err, user){ if(err) throw err; if(!user){ return done(null, false, {message: 'Unknown Email Address'}); } // 打印用户对象,查看是否存在password字段 console.log('查询到的用户对象:', user); User.comparePassword(password, user.password, function(err, ismatch){ if(err) throw err; if(ismatch){ return done(null, user); } else { return done(null, false, {message: 'Invalid password'}); } }); }); }));
4. 检查User模型的Schema定义
确保Schema里正确定义了password字段:
const userSchema = new mongoose.Schema({ email: { type: String, required: true, unique: true }, password: { type: String, required: true }, // 其他字段... });
总结
先从注册逻辑和查询逻辑入手,确认密码哈希是否正确保存、查询时是否获取到了password字段,这两个点是最可能导致问题的原因。通过添加日志打印用户对象,可以快速定位到问题所在。
内容的提问来源于stack exchange,提问作者user8331511
相关产品推荐
相关产品推荐

