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

Mongoose返回ObjectId对象而非纯ID字符串,JWT生成token时如何解决?

ObjectId转纯字符串修复方案

问题原因

Mongoose 从MongoDB查询返回的文档中,_id字段默认是ObjectId类型的实例对象,而非纯字符串,因此直接打印时会输出new ObjectId("xxx")的格式,需要手动转换为字符串后再用于生成token等场景。

修复方法

方法1:调用toString()转换(最常用)

直接在需要使用纯ID的位置对user._id调用toString()方法即可获取24位纯ID字符串,修改核心代码如下:

// 生成token时转换
const token = jwt.sign({ userId: user._id.toString() }, process.env.LOGIN_TOKEN, {
  expiresIn: "1h",
});
// 返回结果时也可按需转换
res.status(200).json({ user: user._id.toString() });

方法2:调用toHexString()转换

ObjectId实例自带toHexString()方法,专门用于获取十六进制格式的ID字符串,用法和toString()一致:

const strId = user._id.toHexString();

方法3:查询时加lean()(可选优化)

如果不需要使用Mongoose文档的实例方法,查询时添加lean()会直接返回普通JavaScript对象,既可以提升查询性能,也能更方便地处理字段:

const user = await UserModel.findOne({ email: email }).lean();

额外代码优化

你当前代码存在重复查询的冗余逻辑:密码校验前已经查询过一次用户数据,try块内不需要再次查询,可以直接复用之前的user变量,同时补充用户不存在的异常判断,避免运行时报错。优化后的完整代码如下:

module.exports.login = async (req, res) => {
  const { email, password } = req.body;
  try {
    // 仅查询一次用户数据
    const user = await UserModel.findOne({ email: email });
    if (!user) {
      return res.status(400).json({ message: "用户不存在" });
    }
    const match = await bcrypt.compare(password, user.password);
  
    if (match) {
      console.log(user._id.toString());
      // 生成token
      const token = jwt.sign({ userId: user._id.toString() }, process.env.LOGIN_TOKEN, {
        expiresIn: "1h",
      });
      console.log(token);
      res.cookie("jwt", token, { httpOnly: true});
      res.status(200).json({ user: user._id.toString() });
    } else {
      res.status(400).json({ message: "密码错误" });
    }
  } catch (err) {
    res.status(500).json(err);
  }
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 11:09:04