Node.js中MongoDB存储的Session跨JS文件访问不持久化返回undefined排查
1. 核心问题:中间件挂载顺序完全颠倒
Express 中间件严格按照代码书写顺序执行,你在 app.js 中的挂载顺序直接断了session的读写链路:
- 当前顺序:先挂载
passport.initialize()、passport.session(),最后才挂载express-session中间件 - 这就导致passport的会话处理逻辑执行时,
req对象上根本还没有挂载session属性(负责加载、写入session的express-session还没执行),passport的会话能力直接静默失效。
必须遵守的执行链路顺序:接收请求 → 先执行express-session,从MongoDB匹配对应sid的session数据挂到
req上 → 再执行passport初始化与会话逻辑 → 最后进入路由处理业务。
// 修正后的正确中间件挂载顺序 app.use(cors({ credentials: true })) app.use(bodyParser.json()) app.use(bodyParser.urlencoded({ extended: true })) app.use(cookieparser()) app.use(express.static(__dirname +'/assets')); // 第一步:优先挂载express-session app.use( session({ secret: 'keyboard', resave: false, saveUninitialized: false, store: MongoStore.create({ mongoUrl: config.mongoUri }), // 补充生产环境必要的cookie配置 cookie: { maxAge: 1000 * 60 * 60 * 24, secure: process.env.NODE_ENV === 'production', sameSite: process.env.NODE_ENV === 'production' ? 'none' : 'lax' } }) ) // 第二步:session挂载完成后,再挂载passport相关中间件 app.use(passport.initialize()); app.use(passport.session()); // 后续数据库连接、路由配置保持原有逻辑即可 mongoose.connect(config.mongoUri,{ useNewUrlParser: true },()=>{ console.log('connected to db') }) mongoose.set('useFindAndModify', false); mongoose.connection.on('error', () => { throw new Error(`unable to connect to database`) }) app.use('/', userRoutes) app.use('/', authRoutes) app.use('/', postRoutes)
2. 跨域配置缺失,导致浏览器不携带session Cookie
你现在用默认的 cors() 配置,默认是不允许跨域请求携带身份凭证的。就算服务端正常把session存在MongoDB、把sid的Cookie种到了浏览器上,跨域场景下浏览器根本不会把这个Cookie带给服务器,服务器找不到匹配的session,自然读出来的req.session.user就是undefined。
这也解释了为什么你在auth回调里能打印出存好的session数据——那是登录回调的单次请求,已经种上了sid的Cookie,但后续的其他请求如果没有带这个Cookie,服务器就会生成全新的空session,自然读不到之前存的用户信息。
- 修复要求:服务端cors必须开启
credentials: true,前端发请求时也要同步开启withCredentials: true,才能正常携带Cookie。
3. 生产环境Cookie配置不全
原session配置没有任何Cookie相关参数,你部署在Heroku的HTTPS环境下,浏览器的安全规则会直接拦截没有设置secure、sameSite属性的Cookie,导致Cookie无法正常存储和传输,上面的代码块已经补充了对应适配配置。
4. requireSignin 中间件写法错误
你当前的逻辑是直接执行expressJwt()函数,把返回的中间件对象放到if条件里,函数对象本身永远是真值,根本起不到实际校验作用。同时算法配置里混入了sha1这种expressJwt不支持的无效算法,会导致校验异常。
修正后的代码:
const requireSignin = (req, res, next) => { console.log(req.session.user) // 优先校验session是否存在有效用户 if (req.session.user) { return next(); } // 无session用户时,再执行JWT校验 expressJwt({ secret: config.jwtSecret, userProperty: "auth", algorithms: ["HS256"] })(req, res, next) };
额外排查提示
- 打开浏览器开发者工具的应用面板,检查是否能正常看到
connect.sid的Cookie,如果看不到,基本是Cookie的secure、sameSite配置不对,或者cors没有开启凭证携带 - 确认MongoStore连接的数据库和mongoose连接的是同一个实例,避免session存在其他库中导致读取失败
- 不要在GoogleStrategy的回调里用全局变量存储用户信息,并发请求时会出现数据串号问题,直接通过passport的序列化逻辑存入session即可,不需要手动操作
req.session.user
内容的提问来源于stack exchange,提问作者Himanshu Ranjan

