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

无法为Mongoose查询结果添加time属性到JWT,求解决方法

问题分析与解决方案

我看了你的代码,问题主要出在变量作用域和逻辑执行顺序上,还有对Mongoose对象toJSON()方法的理解偏差,导致time字段根本没被加入到JWT的 payload 里。

具体问题点:

  • 变量作用域错误:loginDetailsAfterSaving是在newLogin.save()的回调函数内部定义的,你在回调外面写的user.time=loginDetailsAfterSaving.time这些代码根本访问不到这个变量,等于白写。
  • 逻辑分支缺失:当用户已经登录(loginDetails !== null)的情况,你完全没有处理获取loginDetails.time并添加到user对象的逻辑。
  • 无效的对象修改:user.toJSON().time=...这种写法是错的,因为toJSON()会返回一个新的普通JS对象,修改这个新对象不会影响原来的user Mongoose文档对象。

修正后的代码:

Login.findOne({ email: req.body.email }, (err, loginDetails) => {
  if (err) {
    return res.status(500).send(err);
  }

  // 提取复用逻辑,避免重复代码
  let generateAndSendToken = (loginTime) => {
    // 把time字段添加到user对象上
    user.time = loginTime;
    // 用更新后的user对象生成JWT
    let token = jsonwebtoken.sign(user.toJSON(), "example1");
    res.status(200).json({ token: token });
  };

  if (!loginDetails) {
    // 用户尚未登录,保存新的登录信息
    let newLogin = new Login();
    newLogin.email = req.body.email;
    newLogin.userType = user.userType;
    newLogin.save((err, savedLogin) => {
      if (err) {
        return res.status(500).send(err);
      }
      // 保存成功后,用新记录的time生成token
      generateAndSendToken(savedLogin.time);
    });
  } else {
    // 用户已登录,直接用现有记录的time生成token
    generateAndSendToken(loginDetails.time);
  }
});

关键修改说明:

  1. 提取了generateAndSendToken函数复用JWT生成逻辑,确保time字段在生成token前已经被正确添加到user对象。
  2. 在首次登录的save回调里,直接使用savedLogin.time调用token生成函数,保证能拿到最新的登录时间。
  3. 补全了用户已登录的分支,直接使用loginDetails.time添加到user对象。
  4. 直接修改user.time——Mongoose文档对象允许添加自定义字段(即使不在Schema中定义),转成JSON时会自动包含这个新字段。

这样修改后,生成的JWT payload里就会包含time字段,Angular端解码后就能正常看到了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:03:37