如何在两台本地Express服务器间共享express-session存储的数据
实现方案
默认express-session的存储是服务进程内存,不同服务的内存完全隔离,要实现跨服务共享session需要配置共享的外部session存储,同时统一两边的session配置,具体修改步骤如下:
步骤1:安装所需依赖
两个服务的项目都需要安装以下依赖:
npm install express-session # 选用你已有的MySQL作为共享存储的话额外安装 npm install express-mysql-session
步骤2:修改第一台API服务的代码
2.1 新增session配置
在apiApp.use(cors())之前新增session和存储配置,注意所有配置项后续第二台服务要完全一致:
const session = require('express-session'); const MySQLStore = require('express-mysql-session')(session); // 配置session存储,用你现有的MySQL连接参数 const sessionStore = new MySQLStore({ host: 'localhost', user: process.env.DB_USER, password: process.env.DB_PASS, database: process.env.DB_NAME, clearExpired: true, checkExpirationInterval: 900000, // 15分钟清理一次过期session expiration: 86400000 // session有效期1天 }, pool); // 复用你已经创建的mysql连接池 // 配置session,注意配置项两边服务完全一致 apiApp.use(session({ name: 'YOUR_SESSION_COOKIE_NAME', // 自定义cookie名,两边要一样 secret: 'YOUR_SECRET_KEY_HERE', // 自定义加密秘钥,两边要一样,不要泄露 resave: false, saveUninitialized: false, store: sessionStore, cookie: { httpOnly: true, maxAge: 86400000, // 和上面的有效期一致 sameSite: 'lax', // 本地测试如果跨端口可以设为none,但要配合secure: true和https secure: process.env.NODE_ENV === 'production' // 生产环境开https设为true } })); // 修改CORS配置,支持跨域带cookie apiApp.use(cors({ origin: 'http://你的第二台服务的地址:端口', // 不能用*,要指定第二台服务的实际地址 credentials: true }));
2.2 修正登录接口的session赋值顺序
你原来的代码先执行res.send(true)再赋值session,会导致session还没持久化就返回了,修改为:
if (results[0] && !error) { req.session.courriel = req.body.courriel; // 先赋值session res.send(true); // 再返回响应 } else { res.send(false); }
步骤3:修改第二台页面服务的代码
3.1 新增完全相同的session配置
在coreApp.use(cors())之前新增和第一台服务完全一致的session配置:
const session = require('express-session'); const MySQLStore = require('express-mysql-session')(session); const mysql = require("mysql"); // 创建和第一台服务完全相同的mysql连接池 const pool = mysql.createPool({ user: process.env.DB_USER, password: process.env.DB_PASS, database: process.env.DB_NAME, host: "localhost" }); const sessionStore = new MySQLStore({ host: 'localhost', user: process.env.DB_USER, password: process.env.DB_PASS, database: process.env.DB_NAME, clearExpired: true, checkExpirationInterval: 900000, expiration: 86400000 }, pool); coreApp.use(session({ name: 'YOUR_SESSION_COOKIE_NAME', // 和第一台服务完全一致 secret: 'YOUR_SECRET_KEY_HERE', // 和第一台服务完全一致 resave: false, saveUninitialized: false, store: sessionStore, cookie: { httpOnly: true, maxAge: 86400000, sameSite: 'lax', secure: process.env.NODE_ENV === 'production' } })); // 修正CORS配置,和第一台保持一致 coreApp.use(cors({ origin: 'http://你的第一台API服务的地址:端口', credentials: true }));
3.2 前端请求注意事项
如果你的前端页面是从第二台服务加载,请求第一台的登录接口时,需要开启携带凭证:
- 用axios的话设置
withCredentials: true - 用fetch的话设置
credentials: 'include'
验证
修改完成后重启两个服务,调用登录接口后,再访问第二台服务的/connexion路由就可以正常读到req.session.courriel的值。
内容的提问来源于stack exchange,提问作者Daniel Boisclair
相关产品推荐
相关产品推荐

