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

部署EC2后Express-session无法在请求头设置Cookie的问题

Node.js后端部署到EC2后无法在请求头携带Cookie的问题

将Node.js后端部署到EC2后,服务地址变为http://52.xx.xx.xx:8080,出现前端请求无法在请求头中携带Cookie的问题,导致SSO验证失败。

流程说明

  • 用户在前端(localhost:5173)点击“登录”,重定向到SSO服务器(http://localhost:8080/login?serviceURL=localhost:5173)完成登录操作;
  • 用户输入邮箱密码后,Passport将SSO服务器的session(sessionId)存入数据库Sessions表,并设置包含该sessionId的Cookie;
  • 客户端携带SSO token及Cookie向SSO服务器发起请求,服务器通过Cookie中的sessionId查询数据库,调用deserializeUser填充req.user。

问题现象

部署到EC2后,浏览器中connect.sid Cookie的域为52.xx.xx.xx,前端调用http://52.xx.xx.xx:8080/verify-token接口时,请求头无法携带Cookie,导致req.user为undefined,接口返回404错误“Not match sso token”。本地localhost:8080环境下功能正常。

已尝试设置Cookie的sameSite为"lax",但无效。

相关配置代码

config.session配置

app.use(
    session({
      secret: "keyboard cat",
      store: myStore,
      resave: false, // 我们支持touch方法,根据express-session文档应设为false
      proxy: true, // 若在node之外使用SSL
      saveUninitialized: false,
      checkExpirationInterval: 15 * 60 * 1000, // 清理过期会话的时间间隔(毫秒)
      expiration: 500 * 1000,
      cookie: {
        httpOnly: true,
        maxAge: 24 * 60 * 60 * 1000,
        secure: false,
        path: "/",
      },
    })
  );
  // 正常继续执行
  myStore.sync();
  app.use(passport.authenticate("session"));

  passport.serializeUser(function (user, cb) {
    process.nextTick(function () {
      //   cb(null, { id: user.id, username: user.username });
      cb(null, user);
    });
  });
  passport.deserializeUser(function (user, cb) {
    process.nextTick(function () {
      return cb(null, user);
    });
  });
};

loginController.js配置

const getLoginPage = (req, res) => {
  const { serviceURL } = req.query;
  return res.render("login.ejs", {
    redirectURL: serviceURL,
  });
};

const verifySSOToken = async (req, res) => {
  try {
    const { ssoToken } = req.body;
    console.log("check code from req.user", req.user);
    if (req.user && req.user.code && req.user.code === ssoToken) {
      const refreshToken = uuidv4();
      //更新用户refresh token
      await AuthService.updateRefreshToken(req.user.email, refreshToken);

      let payload = {
        user_id: req.user.user_id,
        roleWithPermission: req.user.roleWithPermission,
        first_name: req.user.first_name,
        last_name: req.user.last_name,
        phone: req.user.phone,
        address: req.user.address,
        email: req.user.email,
      };

      let token = createToken(payload);

      //设置cookies
      res.cookie("refresh_token", refreshToken, {
        httpOnly: true,
        maxAge: 60 * 60 * 24 * 1000,
        secure: false,
        path: "/",
      });
      res.cookie("access_token", token, {
        httpOnly: true,
        maxAge: 60 * 60 * 1000,
        secure: false,
        path: "/",
      });

      const resData = {
        user_id: req.user.user_id,
        access_token: token,
        refresh_token: refreshToken,
        email: req.user.email,
        first_name: req.user.first_name,
        last_name: req.user.last_name,
        phone: req.user.phone,
        address: req.user.address,
        roleWithPermission: req.user.roleWithPermission,
      };

      //销毁会话
      req.session.destroy(function (err) {
        req.logout();
      });

      return new OK({
        EM: "Verify token successfully",
        DT: resData,
      }).send(res);
    } else {
      throw new UnauthorizedResponse({
        EM: "Not match sso token",
        DT: "",
      });
    }
  } catch (error) {
    console.log(error);
    if (error instanceof ErrorResponse) {
      return error.send(res);
    }
    return new ErrorResponse({
      EM: "Error verifying SSO token from server",
    }).send(res);
  }
};

passportController.js配置

import passport from "passport";
import LocalStrategy from "passport-local";
import AuthService from "../services/auth.service";
const configPassport = () => {
  passport.use(
    new LocalStrategy({}, async (username, password, done) => {
      try {
        const rawData = {
          valueLogin: username,
          password: password,
        };
        const user = await AuthService.login(rawData);
        console.log("Check user passport Controller", user);
        if (user && +user.EC === 1) {
          return done(null, user.DT);
        } else {
          return done(null, false, { message: user.EM });
        }
      } catch (error) {
        console.error("Login error:", error);
        return done(error);
      }
    })
  );
};

const handleLogout = (req, res) => {
  //   req.logout();
  //   res.redirect("/login");

  req.session.destroy(function (err) {
    req.logout();
    res.redirect("/");
  });
};

export { configPassport, handleLogout };

CORS配置

require("dotenv").config();
const allowedOrigins = [
  "*",
  process.env.REACT_PATH,
  process.env.REACT_PATH_SSO, //localhost:5173
  process.env.SERVICE_PATH,
  process.env.DOCKER_SSO_PATH,
  process.env.DOCKER_SSO_PATH + "/api/v1",
  "http://" + process.env.HOST_NAME + ":" + process.env.PORT, //localhost:8080
  process.env.PUBLIC_SSO_PATH, //http://52.xx.xx.xx:8080
  process.env.PUBLIC_SSO_PATH + "/api/v1",
  process.env.PRIVATE_SSO_PATH,
  process.env.PRIVATE_SSO_PATH + "/api/v1",
  process.env.SERVICE_PATH,
].filter(Boolean);

module.exports = allowedOrigins;
import allowedOrigins from "./allowedOrigin";

const corsOption = {
  origin: (origin, callback) => {
    if (allowedOrigins.indexOf(origin) !== -1 || !origin) {
      callback(null, true);
    } else {
      callback(new Error("Not allowed by CORS"));
    }
  },
  methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
  allowedHeaders: [
    "Content-Type",
    "Authorization",
    "X-Requested-With",
    "Access-Control-Allow-Credentials",
  ],
  exposedHeaders: [
    "Set-Cookie",
    "Access-Control-Allow-Credentials",
    "set-cookie",
  ],
  credentials: true,
  optionsSuccessStatus: 200,
};

export default corsOption;
import allowedOrigins from "../configs/CORS/allowedOrigin";

const credentials = (req, res, next) => {
  const origin = req.headers.origin;
  if (allowedOrigins.includes(origin)) {
    res.header("Access-Control-Allow-Credentials", true);
  }
  next();
};

export default credentials;

相关截图

截图1
截图2

内容的提问来源于stack exchange,提问作者Thuận Phát

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 00:18:12