Express路由中ObjectId转换失败与读取undefined的_id属性错误求助
Express路由中ObjectId转换失败与读取undefined的_id属性错误求助
嘿,我帮你排查一下这两个错误的根源,咱们逐个解决:
第一个错误:Cast to ObjectId failed(authUser函数)
这个错误是因为你在验证用户时用错了Mongoose查询方法!你写的是:
const user = await User.findById({ email });
findById方法是专门用来根据_id字段查询文档的,你传了一个包含email的对象,Mongoose会尝试把这个对象转换成ObjectId类型,自然就失败了。
修复方法:把findById改成findOne,和注册用户时的查询逻辑一致:
const user = await User.findOne({ email });
第二个错误:Cannot read properties of undefined (reading '_id')(getUserProfile函数)
这个问题是因为req.user没有被正确赋值,导致读取req.user._id时报错,根源在三个地方:
1. 路由没有添加权限验证中间件
你的/profile路由没有使用protect中间件,所以请求不会经过token验证流程,req.user自然是undefined。
修复路由(routes/authRoutes.js):
router.get('/profile', protect, getUserProfile); // 加上protect中间件
2. authMiddleware里的几处语法错误
split('')应该是split(' '):Bearer和token之间是空格分隔,你用空字符串分割会把每个字符拆分开,导致token无效。findBy是不存在的方法,应该用findById。- 解码后的字段是
_id不是id:因为你生成token时用的是{ _id },所以decoded里的键是_id。
修复authMiddleware.js:
const protect = asyncHandler(async (req, res, next) => { let token; if(req.headers.authorization && req.headers.authorization.startsWith('Bearer')){ try{ token = req.headers.authorization.split(' ')[1]; // 改成split(' ') const decoded = jwt.verify(token, process.env.JWT_SECRET); req.user = await User.findById(decoded._id).select('-password'); // 改成findById和decoded._id next(); } catch(err){ console.log(err); res.status(401); throw new Error('Not authorized, token failed'); } } if(!token){ res.status(401); throw new Error('Not authorized, no token'); } });
其他需要修复的小问题
除了上面两个核心错误,还有几个细节问题会导致潜在bug:
1. Notes模型错误(models/Notes.js)
你导出时用了UserSchema,应该是NotesSchema:
const Notes = mongoose.model('Notes', NotesSchema); // 把UserSchema改成NotesSchema
2. errorMiddleware里的拼写错误
req.orginalUrl应该是req.originalUrl(少了一个i):
const error = new Error(`Not Found - ${req.originalUrl}`);
3. .env文件格式错误
.env里不要加引号和分号,正确格式是:
JWT_SECRET=Chaleya NODE_ENV=production
把这些修改完之后,再测试一下authUser和getUserProfile接口,应该就能正常工作了!
备注:内容来源于stack exchange,提问作者Radical Rosh
相关产品推荐
相关产品推荐

