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

为什么MongoDB中findOne()无返回值?密码重置路由故障求助

密码重置POST路由问题解决方案

核心问题1:User.findOne()始终返回null

排查和修复步骤:

  • 核对字段匹配:先打印console.log(req.body.username)确认请求携带的参数值是正确的邮箱,再检查User模型定义,确认存储用户邮箱的字段名确实是email,如果模型中邮箱字段名为username或者其他命名,修改查询条件为对应的字段即可
  • 确认数据存在且大小写匹配:检查数据库中对应集合的用户数据,确认待查询的邮箱确实存在。部分数据库对字符串查询默认大小写敏感,如果存在大小写不一致的情况,统一转小写后再查询和存储:
// 查询时统一转小写
const user = await User.findOne({ email: req.body.username.toLowerCase() });
  • 确认模型配置正确:检查User模型和数据库的连接是否正常,findOne方法是否能正常返回Promise,没有出现模型导入错误、连接异常等问题。

核心问题2:token undefined报错

报错的根本原因是async语法和async.waterfall回调机制混用冲突:你给waterfall的第二个任务函数添加了async关键字,async函数默认会返回Promise,不会自动触发waterfall的done回调,打断了参数传递链,导致后续任务无法拿到正确的token值。
修复方案参考:

方案1:适配async.waterfall 去掉async/await,改用回调写法

function(token, done) {
  User.findOne({ email: req.body.username }, function(err, user) {
    if (err) return done(err);
    if (!user) {
      req.flash('error', 'No account with that email address exists.');
      return res.redirect('/forget-password');
    }
    user.resetPasswordToken = token;
    user.resetPasswordExpires = Date.now() + 3600000; // 1小时有效期
    user.save(function(err) {
      done(err, token, user);
    });
  });
},

方案2:完全改用async/await语法,弃用async.waterfall

重写后的整体逻辑更简洁,避免回调嵌套问题:

app.post('/check-auth', async (req, res, next) => {
  try {
    // 生成token
    const buf = crypto.randomBytes(20);
    const token = buf.toString('hex');
    // 查询用户
    const user = await User.findOne({ email: req.body.username });
    if (!user) {
      req.flash('error', 'No account with that email address exists.');
      return res.redirect('/forget-password');
    }
    // 保存重置信息
    user.resetPasswordToken = token;
    user.resetPasswordExpires = Date.now() + 3600000;
    await user.save();
    // 发送邮件
    const smtpTransport = nodemailer.createTransport({
      service: 'Gmail',
      auth: {
        user: 'xyz@gmail.com',
        pass: 'jvjvsdjfvjdvjdvdv'
      }
    });
    const mailOptions = {
      from: 'passwordreset@demo.com',
      to: req.body.username,
      subject: 'Node.js Password Reset',
      text: 'You are receiving this because you (or someone else) have requested the reset of the password for your account.\n\n' +
        'Please click on the following link, or paste this into your browser to complete the process:\n\n' +
        'http://' + req.headers.host + '/reset/' + token + '\n\n' +
        'If you did not request this, please ignore this email and your password will remain unchanged.\n'
    };
    await smtpTransport.sendMail(mailOptions);
    req.flash('info', 'An e-mail has been sent to ' + user.email + ' with further instructions.');
    res.redirect('/forgot');
  } catch (err) {
    next(err);
  }
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 08:36:03