generateAuthToken()注册有效但登录时返回Undefined技术求助
问题分析与解决方法
核心原因
登录时调用generateAuthToken()返回undefined,大概率是以下两个原因之一:
1. generateAuthToken不是Truck模型的实例方法
如果你的generateAuthToken是定义为静态方法(用TruckSchema.statics.generateAuthToken),那只有Truck模型本身能调用,从数据库查询出来的实例(registerUser)无法调用这个方法,自然返回undefined。
正确的实例方法定义应该挂载到Schema的methods上:
const TruckSchema = new mongoose.Schema({ email: String, pword: String }); // 实例方法:每个Truck实例都能调用 TruckSchema.methods.generateAuthToken = async function() { const user = this; const token = jwt.sign({ _id: user._id.toString() }, process.env.SECRET_KEY, { expiresIn: '24h' }); // 如果需要将token保存到用户文档(比如支持多设备登录) // user.tokens = user.tokens.concat({ token }); // await user.save(); return token; }; const Truck = mongoose.model('Truck', TruckSchema);
2. 查询返回的是普通对象而非Mongoose文档实例
如果查询时用了lean()选项,findOne会返回普通JavaScript对象,而不是带有原型方法的Mongoose文档实例,这时候调用generateAuthToken()会因为方法不存在而返回undefined。
检查你的查询代码,确保没有加lean():
// 错误写法:加了lean()返回普通对象 const registerUser = await Truck.findOne({email:email}).lean(); // 正确写法:返回Mongoose文档实例 const registerUser = await Truck.findOne({email:email});
附带优化建议
- 登录逻辑顺序调整:先验证密码是否匹配,再生成token,避免无效操作:
const isMatch = await bcrypt.compare(pword, registerUser.pword); if (isMatch) { const token = await registerUser.generateAuthToken(); // 设置cookie、返回响应 } else { res.status(400).send("登录失败,密码错误"); }
- 注册时加密密码:现在注册是直接存明文密码,严重违反安全规范,必须先加密再保存:
const registerUser = new Truck({ email: req.body.email, pword: await bcrypt.hash(req.body.pword, 10) // 加密密码 });
内容的提问来源于stack exchange,提问作者Omanpreet Singh
相关产品推荐
相关产品推荐

