Passport Google登录后req.user缺失ObjectId问题修复咨询
修复Passport Google登录后req.user缺失ObjectId的问题
问题根源
你的代码在Google OAuth的验证回调中,当用户已存在时,错误地将Google返回的profile对象传递给了done()函数,而非数据库中存储的完整用户文档。这会导致:
serializeUser接收到的不是带有_id的MongoDB用户对象,无法正确序列化用户ID- 后续
deserializeUser无法通过正确的ID查询到完整用户,最终req.user只包含profile中的字段(如googleId)
修复步骤
1. 修正GoogleStrategy的验证回调
将用户存在分支中的return done(null, profile)改为return done(null, user),确保传递给Passport的是数据库中的用户对象:
passport.use(new GoogleStrategy({ clientID: process.env.CLIENT_ID, clientSecret: process.env.CLIENT_SECRET, callbackURL: "http://localhost:3000/auth/google/secrets", scope:["profile", "email"] }, function(accessToken, refreshToken, profile, done) { User.findOne({googleId:profile["id"]}).then(user=>{ if (!user){ const newUser=new User({ email:profile.emails[0].value, googleId:profile.id }) newUser.save().then(resolve=>{return done(null, newUser);}).catch(error=>{console.log(error)}) } else{ // 修复:传递数据库中的user对象而非profile return done(null, user) } }).catch(error=>{return done(error)}) } ));
2. 优化/submit接口的用户查询逻辑
原代码中依赖googleId查询用户,只适用于Google登录用户,改为通过通用的_id查询,兼容所有登录方式:
app.post("/submit", (req, res)=>{ console.log(req.user); // 使用用户的_id更新,兼容本地和Google登录用户 User.findByIdAndUpdate(req.user._id, {secret: req.body.secret}) .then(() => res.redirect("/secrets")) .catch(error => console.log(error)); })
额外优化建议
- 完善错误传递:
newUser.save()的错误当前仅打印,建议改为newUser.save().then(resolve=>done(null, resolve)).catch(error=>done(error)),确保Passport能捕获创建用户时的错误 - 保持现有序列化逻辑:当前的
serializeUser和deserializeUser是通用的正确实现,无需修改
内容的提问来源于stack exchange,提问作者brazilclouds
相关产品推荐
相关产品推荐

