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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:07:24