Battle.Net OAuth新访问者无需重新登录 全局user变量覆盖问题求助
问题根因
- 你在代码最顶层声明了全局作用域的
let user = {}变量,Node.js服务端的全局变量是所有请求共享的,只要有一个用户登录修改了这个全局user,所有后续访问的用户拿到的都是这个值,这就是所有新访客都登录到你账号的直接原因 - 你只引入了
passport.initialize()中间件,没有配置express-session和passport.session()中间件,Passport本身需要依赖会话来存储每个用户独立的登录信息
修复步骤
- 先安装express-session依赖:
npm install express-session - 删除最顶层的
let user = {}全局变量,完全不要用全局变量存储用户信息 - 引入express-session并配置,放在passport初始化之前:
import session from 'express-session'; // 放在passport.initialize()前面 app.use(session({ secret: '自行设置一个安全的随机字符串', resave: false, saveUninitialized: false, cookie: { secure: false } // 生产环境如果是HTTPS要改成true })); app.use(passport.initialize()); app.use(passport.session()); // 新增这行,启用Passport的会话支持
- 修改BnetStrategy的验证回调,不需要给全局user赋值,直接返回即可:
passport.use( new BnetStrategy( { clientID: BNET_ID, clientSecret: BNET_SECRET, callbackURL: "http://localhost:5000/auth/bnet/callback", region: "us", scope: "openid", }, function (accessToken, refreshToken, profile, done) { // 删掉user = profile这行,不需要全局存储 return done(null, profile); }, ), );
- 修改
/user接口,从当前请求的会话中取用户,Passport会自动把登录用户信息挂载到req.user上:
app.get("/user", (req, res) => { // 用户未登录时req.user为undefined,可按需返回空对象或者错误提示 res.send(req.user || {}); });
- 修改注销接口,调用Passport提供的
req.logout()方法清空当前用户的会话信息,不要操作全局变量:
app.get("/auth/logout", (req, res, next) => { console.log("logging out!"); req.logout((err) => { if (err) return next(err); res.redirect("http://localhost:3000/"); }); });
补充注意事项
- 生产环境下不要用express-session默认的内存存储,容易出现内存泄漏,建议换成
connect-mongo、connect-redis这类持久化存储方案 - session的secret要放到环境变量里配置,不要硬编码在代码中,避免泄露
- 生产环境的cookie要设置
secure: true、httpOnly: true、sameSite: 'strict',提升安全性 - 如果后续用户数据量较大,可以调整serializeUser只存储用户ID,deserializeUser再通过ID查询完整用户信息,减少session存储占用
内容的提问来源于stack exchange,提问作者Christian Kenney
相关产品推荐
相关产品推荐

