Express+Passport谷歌登录后req.user丢失,会话检查报错排查
问题描述
搭建NodeJS & Express应用,使用Passport实现谷歌登录认证:
- 本地环境登录流程正常,登录后能看到
req.user包含完整用户信息 - 后续调用任意路由时
req.user变为undefined - 尝试添加登录检查中间件重定向到登录页,出现
ECONNRESET错误
相关代码
const express = require("express"); const passport = require("passport"); const GoogleStrategy = require("passport-google-oauth20").Strategy; const app = express() const port = 5000 // if user is not logged-in redirect back to login page app.use(function(req, res, next) { if (req.session.user == null){ res.redirect('http://localhost:3000/login'); } else { next(); } }); app.use( session({ secret: 'keyboard cat', resave: false, cookie: { httpOnly: false, secure: false, maxAge: 60 * 1000}, saveUninitialized: false, }) ) passport.use( new GoogleStrategy({ clientID: "process.env.clientID", clientSecret: "process.env.clientSecret", callbackURL: '/auth/google/callback', }, async (accessToken, refreshToken, profile, done) => { const existingUser = await User.findOne({ providerId: profile.id, }) if (existingUser) { return done(null, existingUser); } const user = await new User({ provider: profile.provider, providerId: profile.id, displayName: profile.displayName, }).save() done(null, user); }) ) passport.serializeUser(function (user, done) { done(null, user.id); }); passport.deserializeUser(function (obj, done) { done(null, done); });
报错信息
ERROR Error in fetch(): request to http://localhost:3000/login failed, reason: read ECONNRESET at ClientRequest.<anonymous> (node_modules/node-fetch/lib/index.js:1461:11) at ClientRequest.emit (events.js:400:28) at Socket.socketErrorListener (_http_client.js:475:9) at Socket.emit (events.js:400:28) at emitErrorNT (internal/streams/destroy.js:106:8) at emitErrorCloseNT (internal/streams/destroy.js:74:3) at processTicksAndRejections (internal/process/task_queues.js:82:21)
修复方案
1. 修正中间件加载顺序
Express中间件按执行顺序加载,登录检查逻辑必须放在session和Passport初始化之后,同时要排除登录相关路由避免无限重定向:
// 先加载session中间件 app.use( session({ secret: 'keyboard cat', resave: false, cookie: { httpOnly: true, secure: false, maxAge: 60 * 1000}, // 建议开启httpOnly提升安全性 saveUninitialized: false, }) ) // 初始化Passport app.use(passport.initialize()); app.use(passport.session()); // 必须在session中间件之后加载 // 登录检查中间件:跳过登录授权及回调路由 app.use(function(req, res, next) { const authRoutes = ['/auth/google', '/auth/google/callback']; if (authRoutes.includes(req.path)) { return next(); } // Passport将用户信息存在req.user而非req.session.user if (!req.user) { return res.redirect('http://localhost:3000/login'); } next(); });
2. 修复deserializeUser逻辑
当前代码错误地将done函数作为用户对象返回,需根据序列化的user.id查询用户并返回:
passport.deserializeUser(async function (userId, done) { try { const user = await User.findById(userId); done(null, user); } catch (err) { done(err, null); } });
3. 正确读取环境变量
不要用字符串包裹process.env变量,否则会读取到字面量字符串而非实际环境变量:
passport.use( new GoogleStrategy({ clientID: process.env.clientID, // 去掉引号 clientSecret: process.env.clientSecret, // 去掉引号 callbackURL: '/auth/google/callback', }, // 其余逻辑保持不变 ) )
4. 解决ECONNRESET错误
该错误通常由以下原因导致:
- 前端
localhost:3000服务未启动,后端重定向请求失败 - 登录检查中间件未排除登录路由,导致无限重定向触发连接重置
按步骤1修复中间件后,确保前端服务正常运行即可解决。
内容的提问来源于stack exchange,提问作者Thestrike95
相关产品推荐
相关产品推荐

