You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Express路由间Session数据不一致问题求助(Steam+Passport认证)

问题描述

我是Node.js和Express新手,用Express+Passport.js实现Steam登录认证并存储用户数据。Steam登录后跳转首页功能正常,但访问/lobby路由时,获取的req.session数据和主应用里的不一致。

相关代码

./routes/steamAuth.mjs

import express from 'express';
import passport from 'passport';

const steamAuth = express.Router();

steamAuth.get('/auth/steam', passport.authenticate('steam'));

steamAuth.get('/auth/steam/return',
    passport.authenticate('steam', { failureRedirect: '/' }),
    (req, res, next) => {
      // 🔐 Manually persist user into session (needed if it isn't auto-saved)
      req.login(req.user, (err) => {
        if (err) return next(err);
      
        req.session.save((err) => {
          if (err) return next(err);
      
          console.log("✅ Session forcibly saved:", req.session);
          testSess = req.user;
          res.redirect('/');
        });
      });
    }
  );

export default steamAuth;

主应用代码

passport.serializeUser((user, done) => done(null, user));
passport.deserializeUser((obj, done) => done(null, obj));

passport.use(new SteamStrategy({
  returnURL: 'https://www.explorar.art/steamAuth/auth/steam/return',
  realm: 'https://www.explorar.art/steamAuth/',
  apiKey: process.env.STEAM_API_KEY
}, (identifier, profile, done) => done(null, profile)));

const store = new PgSession({
  pool,
  tableName: 'session'
});

app.use(session({
  store: store,
  secret: process.env.SECRET_KEY,
  resave: false,
  saveUninitialized: false,
  cookie: {
    sameSite: 'lax',
    maxAge: 30 * 24 * 60 * 60 * 1000,
  }
}));

app.use(passport.initialize());
app.use(passport.session());

app.use(express.json());
app.use(express.static('public'));

import steamAuth from './routes/steamAuth.mjs';
import lobbyRoutes from './routes/lobby.mjs';

app.use('/steamAuth', steamAuth);
app.use('/lobby', lobbyRoutes(app));

app.get('/session-test', (req, res) => {
  console.log('session test ❄️:', res.session)
})

./routes/lobby.mjs

export default function lobbyRoutes(app) {

    const router = express.Router();
    router.use(express.json());

    router.use((req, res, next) => {
      console.log('🐛 lobby.mjs session check:', req.sessionID);
      // console.log('🤍 SESSION RAW:', req.session);
      next();
    });  
return router;
}

问题排查与解决

核心问题点

  • 路由初始化逻辑错误:注册/lobby路由时传入app并新建Router实例,导致该Router没有继承主应用的session、Passport中间件,无法解析已存在的会话,会生成新的空session,自然和主应用的session数据不一致。
  • 重复登录操作:passport.authenticate('steam')已经自动完成req.login()操作,手动重复调用可能导致session状态混乱。

修复步骤

1. 修正lobby路由的导出方式

不需要传入app,直接导出Router实例:

// ./routes/lobby.mjs
import express from 'express';

const router = express.Router();

router.use((req, res, next) => {
  console.log('🐛 lobby.mjs session check:', req.sessionID);
  console.log('🤍 SESSION RAW:', req.session);
  next();
});  

export default router;

2. 修正主应用的路由注册

直接挂载路由,无需传递app参数:

// 主应用代码中
import lobbyRoutes from './routes/lobby.mjs';
// 替换原有的app.use('/lobby', lobbyRoutes(app));
app.use('/lobby', lobbyRoutes);

3. 移除不必要的手动登录逻辑

删除/auth/steam/return中的手动req.login(),简化回调:

// 修改后的steamAuth.mjs回调
steamAuth.get('/auth/steam/return',
  passport.authenticate('steam', { failureRedirect: '/' }),
  (req, res, next) => {
    req.session.save((err) => {
      if (err) return next(err);
      console.log("✅ Session saved:", req.session);
      res.redirect('/');
    });
  }
);

Express配置工作原理讲解

中间件执行顺序

Express中间件按注册顺序依次执行,只有经过前面的中间件处理,后续路由才能访问到对应的上下文:

  1. 先执行session中间件:解析请求Cookie,从PgSession数据库加载会话数据到req.session
  2. 再执行passport.initialize():初始化Passport,挂载req.user等核心对象
  3. 再执行passport.session():从req.session.passport.user中反序列化出用户数据,挂载到req.user
  4. 最后执行路由:此时所有路由都能访问到已初始化的session和用户对象

Router与主App的关系

express.Router()是独立的路由实例,但通过app.use('/path', router)挂载后,主App的中间件会先执行,再进入Router的中间件栈。之前错误地传入app并新建Router,相当于绕过了主App的中间件链,导致session无法被解析。

Passport Steam认证流程

  1. 用户访问/steamAuth/auth/steam,Passport重定向到Steam登录页
  2. 用户登录后,Steam回调到/steamAuth/auth/steam/return
  3. passport.authenticate('steam')验证回调数据,获取用户Profile,自动执行req.login()将用户序列化到session
  4. 会话数据保存到PgSession数据库,后续请求通过Cookie中的sessionID加载已有会话

内容的提问来源于stack exchange,提问作者Arthur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 06:37:33