Next.js+Mongoose+Passport.js环境下req.user为undefined问题求助
问题排查与修复方案
- Passport自定义回调未手动完成登录流程
Passport的passport.authenticate自定义回调不会自动将用户挂载到req对象,也不会自动触发会话写入,校验通过的用户存储在回调的user参数中,你需要显式调用req.logIn完成登录流程:
passport.authenticate('local', (err, user, info) => { if (err) return next(err) if (!user) return res.status(401).json({ error: info.message }) // 手动触发登录,完成用户挂载和会话初始化 req.logIn(user, (err) => { if (err) return next(err) // 此时req.user才会被正确赋值 req.session.user = req.user // 补充后续返回响应的逻辑即可 return res.json({ user: { _id: user._id } }) }) })(req, res, next)
注意:自定义回调模式下,需要手动把req, res, next传给authenticate返回的函数,否则校验逻辑不会执行。
- 数据库连接中间件异步逻辑未等待
你新增的数据库连接中间件如果connectDB是异步方法,直接调用后马上执行next会导致后续逻辑执行时数据库还未连接完成,需要修改为异步中间件:
.use(async (req, res, next) => { await connectDB() next() })
如果已经在login接口里单独写了await connectDB(),可以不用重复在全局auth中间件中添加,避免重复建立连接。
- Passport序列化/反序列化逻辑校验
确认你的../lib/passport文件中已经正确实现了passport.serializeUser和passport.deserializeUser方法,这两个方法是Passport实现会话持久化的必要逻辑,参考示例:
// 序列化:把用户ID存入会话 passport.serializeUser((user, done) => { done(null, user._id) }) // 反序列化:请求时从会话取ID查询完整用户信息挂载到req.user passport.deserializeUser(async (id, done) => { const user = await UserModel.findById(id) done(null, user) })
- 会话配置校验
确认你的环境变量中TOKEN_SECRET已正确配置,缺失该值会导致session加密失败,数据无法写入存储。开发环境下可以直接打印req.session确认会话本身是正常生成的。
内容的提问来源于stack exchange,提问作者Antonio Pavicevac-Ortiz
相关产品推荐
相关产品推荐

