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
相关产品推荐
相关产品推荐

