无法为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对象,修改这个新对象不会影响原来的userMongoose文档对象。
修正后的代码:
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); } });
关键修改说明:
- 提取了
generateAndSendToken函数复用JWT生成逻辑,确保time字段在生成token前已经被正确添加到user对象。 - 在首次登录的save回调里,直接使用
savedLogin.time调用token生成函数,保证能拿到最新的登录时间。 - 补全了用户已登录的分支,直接使用
loginDetails.time添加到user对象。 - 直接修改
user.time——Mongoose文档对象允许添加自定义字段(即使不在Schema中定义),转成JSON时会自动包含这个新字段。
这样修改后,生成的JWT payload里就会包含time字段,Angular端解码后就能正常看到了。
内容的提问来源于stack exchange,提问作者phpdroid
相关产品推荐
相关产品推荐

