Nginx + node.js + express-session 竟然每次获取的session id不同/不一样

本文探讨了如何处理Nginx、Node.js和Express应用中Session ID不一致的问题,涉及跨域、多进程共享、Redis存储和正确使用req.session。通过检查Set-Cookie字段和配置细节,找到问题并提供解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Nginx + node.js + express-session 竟然每次获取的session id不同/不一样.

有没有遇到这种情况,却怎么也查不出原因的?查完奔溃了,我去,这么简单?

用node.js的不同路由,竟然每次请求得到的session id不一样.

打开浏览器开发者模式吧, 查看一下第一个请求的[Response Headers], 发现没有Set-Cookie字段.

1. 于是开始搜索相关解决问题的方法,有的说跨域问题,于是解决了跨域,还是不行.

2. 有的说多进程直接存储在内存不能共享session id,可以使用redis,于是我又装了redis-server,然后在node.js里面使用redis,但还是不行.

上面不行之后查来查去都是这两种解决方法,真的无语,只能按部就班了,搞了一个正常的sample运行.然后对比差异.最终发现第一个请求的[Response Headers], 没有Set-Cookie字段.

下面是怎么解决?

最后发现是请求的时候没有使用req.session.

怎么使用呢?

看我的代码吧:

// this is my node_server.js

const http = require("http");

const cors = require("cors"); // 跨域, 应该不需要这个,加上吧,省的出问题
app.use(cors());

const cookieParser = require("cookie-parser"); // 应该不需要这个,加上吧,省的出问题
app.use(cookieParser());

const express = require("express");
const session = require("express-session");
const redis = require("redis");  //需要安装好redis-server,因为这个只是客户端
let RedisStore = require("connect-redis")(session);
let redisClient = redis.createClient(); // 看,这是客户端吧?

const bodyParser = require("body-parser"); //解析body的,不想要就别要了
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(bodyParser.json());

const indexRouter = require("./node_routes/index.js"); // 我自己的index 路由文件, 处理放这个里面了
const host = "localhost";
const port = 3000;

const app = express();
app.set('trust proxy', 1);
app.use(session({
  store: new RedisStore({
    client: redisClient
  }),
  secret: 'guozongling',
  saveUninitialized: false,
  resave: false,
  cookie: {maxAge: 60 * 1000 * 30}
}));

app.use('/*', indexRouter);  // 使用我的index router

// 监听端口
const server = app.listen(port, function(req){
  const host = server.address().address;
  const port = server.address().port;
});


// this is my index.js file
const express = require("express");
const router = express.Router();

router.get('/', function(req, res, next) {
  try {
    console.log("GET -> "+req.session.id);
    req.session.sign = true;
    const path         = req.path;
    const url          = req.url;
    const originalurl  = req.originalUrl;
    const baseurl  = req.baseUrl;

    next();
  } catch(error) {
    res.end();
  }
});

router.post('/', function(req, res, next) {
  try {
    console.log("POST -> "+req.session.id);
    const path         = req.path;
    const url          = req.url;
    const originalurl  = req.originalUrl;
    const baseurl  = req.baseUrl;

    next();

  } catch(error) {
    res.end();
  }
});

module.exports = router;

在 index.js文件中, router.get('/', function(req, res, next) { ... } 请求处理时使用req.session.sign,也就是使用了req.session,这样就会有 Set-Cookie字段, 那么接下来处理任何分发过来的请求session id都是一样了.

另外, 注意一下,app.use(session({

......

})); 这里的cookie设置,好像也有影响, 写成 cookie{ secure: true, path: '/', maxAge:60*1000*30}也会导致session id不同,还不知道为啥,这个对我来说也没用,就不管了.

比如处理:

GET /init

GET /videos

GET /query

等等

如果没有使用req.session,那么就没有Set-Cookie字段, 不同路由,甚至同一个路由也会改变session id.

希望对一些解决了跨域依旧没解决问题的人有帮助, 查看 [Set-Cookie]字段是线索,一切的起源.

### 使用 Express-Session 的基本配置 在 Node.js Express 框架中,`express-session` 是一种用于管理会话状态的中间件。它允许开发者通过 HTTP 请求存储检索数据到服务器端内存或其他持久化存储中。 以下是关于 `express-session` 配置使用的详细介绍: #### 安装依赖 要使用 `express-session`,首先需要将其作为项目依赖项安装: ```bash npm install express-session ``` #### 基本配置示例 以下是一个简单的 `express-session` 配置实例[^2]: ```javascript const express = require('express'); const session = require('express-session'); const app = express(); // 配置 express-session 中间件 app.use(session({ secret: 'your_secret_key', // 用于签名 session ID 的密钥 resave: false, // 强制保存未修改的会话,默认为 true saveUninitialized: true, // 是否保存未初始化的会话,默认为 true cookie: { maxAge: 60 * 60 * 1000 // 设置 Cookie 过期时间 (毫秒),这里设置为 1 小时 } })); // 测试路由 app.get('/', (req, res) => { if (req.session.views) { req.session.views++; res.setHeader('Content-Type', 'text/html'); res.write(`<p>Views: ${req.session.views}</p>`); res.end(); } else { req.session.views = 1; res.end('Welcome to the session demo. Refresh!'); } }); // 启动服务 app.listen(3000, () => { console.log('Server is running on http://localhost:3000'); }); ``` 上述代码展示了如何创建一个带有会话支持的基础应用,并设置了会话选项如 `secret`, `resave`, `saveUninitialized` `cookie.maxAge`。 #### 关键参数解释 - **secret**: 用于加密会话 ID 的字符串。该值应保持私有并具有足够的复杂度。 - **resave**: 即使会话未被修改也重新保存回存储器。通常建议设为 `false` 来提高性能。 - **saveUninitialized**: 如果启用了此选项,则即使会话从未被修改也会保存到存储器中。对于大多数场景推荐设置为 `true`。 - **cookie**: 控制客户端浏览器上存储的 Cookies 行为,例如过期时间安全性标志。 #### 解决 NginxSession ID 一致问题 如果遇到 Nginx 反向代理环境下每次请求都生成新的 Session ID 的情况,可能是因为缺少跨域共享机制或者反向代理丢失了原始 IP 地址所致[^1]。可以通过调整 Nginx 配置来解决这一问题,例如启用 sticky sessions 或者传递真实的客户端地址给后端服务。 另外,在开发环境中可以尝试禁用安全策略以便调试: ```javascript app.use(session({ secret: 'your_secret', resave: false, saveUninitialized: true, proxy: true, // 当运行于 HTTPS/Nginx 背后的环境时需开启此项 rolling: true // 每次响应都会刷新 Cookie 生命周期 })); ``` #### 数据库集成(可选) 为了实现更可靠的会话持久化,还可以将 `express-session` 结合数据库一起工作,比如 Redis、MongoDB 等[^4]: ```javascript const session = require('express-session'); const MongoDBStore = require('connect-mongodb-session')(session); let store = new MongoDBStore({ uri: 'mongodb://localhost:27017/mydatabase', collection: 'sessions' }); store.on('error', function(error){ console.error(error); }); app.use(session({ secret: 'my-secret-key', resave: false, saveUninitialized: true, store: store // 替换默认内存存储方式 })); ``` 以上介绍了 `express-session` 的基础概念及其常见应用场景下的具体实践方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值