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

Heroku与Netlify部署后Express-Session无法存储会话值问题

跨域会话丢失问题排查与解决

本地环境(客户端localhost:3000、服务端localhost:3005)下,Steam登录后会话功能正常,能正确获取req.session.steamuser。但将服务端部署到Heroku、客户端部署到Netlify后,尽管在/api/auth/steam/return接口中已成功设置req.session.steamuser=req.user,访问/user接口时req.session.steamuser仍为null。


服务端代码(Server.js)

var express = require('express');
var passport = require('passport');
var session = require('express-session');
var passportSteam = require('passport-steam');
const cors = require("cors");
var SteamStrategy = passportSteam.Strategy;
var app = express();
const corsOptions = {
    origin: ["https://stunning-bavarois-0eef55.netlify.app"],
    credentials: true, //access-control-allow-credentials:true
    methods: ["GET", "POST"],
};
app.use(cors(corsOptions));

passport.serializeUser((user, done) => {
    done(null, user);
});
passport.deserializeUser((user, done) => {
    done(null, user);
});
passport.use(new SteamStrategy({
    returnURL: 'https://temtestt.herokuapp.com/api/auth/steam/return',
    realm: 'https://temtestt.herokuapp.com/',
    apiKey: 'MY SECRET API KEY'
}, function (identifier, profile, done) {
    process.nextTick(function () {
        profile.identifier = identifier;
        return done(null, profile);
    });
}
));

app.use(session({
    secret: 'db5910cc8b9dcec166fda1d2c34860b6f8cd932cea641ea39924ed18fe6fc863',
    resave: true,
    
    saveUninitialized: true,
    cookie: {
        SameSite:"none",
        maxAge: 3600000,
        secure:true
    }
}))

// Initiate Strategy
app.use(passport.initialize());
app.use(passport.session());

app.get('/', (req, res) => {
    res.status(200);
    res.send("Welcome to root URL of Server");
});
app.get("/user", (req, res) => {
    if (req.session.steamuser) {
        res.status(200).send(req.session.steamuser)
    }
    else {
        res.send(false)
    }
})
app.get('/api/auth/steam', passport.authenticate('steam', { failureRedirect: '/' }), function (req, res) {
    res.redirect('/')
});
app.get('/api/auth/steam/return', passport.authenticate('steam', { failureRedirect: '/' }), function (req, res) {
    req.session.steamuser = req.user;
    res.redirect('https://stunning-bavarois-0eef55.netlify.app/')
});
app.listen(process.env.PORT || 3005);

客户端代码(App.js)

import { useEffect, useState } from 'react';
import './App.css';
import axios from 'axios';
function App() {
  const [user,setUser]=useState(null);
  
  useEffect(()=>{
    async function getUser(){
      const data = await axios.get("https://temtestt.herokuapp.com/user",{withCredentials:true});
      setUser(data.data);
    }
    getUser();
  },[]);
  return (
    <div className="App">
      <h1>Hello</h1>
      {(user===false||user===null)?<><p>Please log in</p><a href="http://temtestt.herokuapp.com/api/auth/steam/return">Login</a></>:<p>{user.displayName}</p>}
    </div>
  );
}

export default App;

问题原因与解决办法

1. 更换会话存储引擎

Heroku的临时文件系统会导致express-session默认的内存存储失效,应用重启或多实例部署时会话数据直接丢失。必须改用持久化存储,比如Redis或PostgreSQL:

const RedisStore = require('connect-redis').default;
const redis = require('redis');

// 连接Heroku Redis服务
const client = redis.createClient({
  url: process.env.REDIS_URL
});
client.connect().catch(console.error);

// 修改session配置
app.use(session({
  secret: process.env.SESSION_SECRET || 'your-fallback-secret',
  resave: false,
  saveUninitialized: false,
  store: new RedisStore({ client }),
  cookie: {
    SameSite: "none",
    maxAge: 3600000,
    secure: process.env.NODE_ENV === 'production',
    domain: '.herokuapp.com'
  }
}))

2. 修正Cookie配置细节

  • secure属性仅在生产环境开启:本地HTTP环境下设置secure: true会导致浏览器拒绝存储Cookie,生产HTTPS环境才需要启用。
  • 确保SameSite: "none"与secure: true同时存在,否则浏览器会拦截跨域Cookie。

3. 修复客户端登录链接

客户端登录链接使用了HTTP协议,Heroku会强制重定向到HTTPS,可能打断会话流程。同时直接访问/return接口不符合Steam认证流程,应修改为:

<a href="https://temtestt.herokuapp.com/api/auth/steam">Login</a>

4. 简化会话获取逻辑

Passport会自动将认证用户信息存在req.user中,无需手动设置req.session.steamuser,直接用Passport提供的req.isAuthenticated()判断状态:

app.get("/user", (req, res) => {
    if (req.isAuthenticated()) {
        res.status(200).send(req.user)
    }
    else {
        res.send(false)
    }
})

5. 改用环境变量管理敏感信息

将session secret、Steam API Key等敏感信息从代码中移除,通过Heroku环境变量配置,避免泄露且适配多环境需求。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 14:50:26