Nodejs 使用redis存储session会话状态的疑惑

Nodejs 使用redis存储session会话状态的疑惑

我是nodejs小鸟,最近对nodejs产生了浓厚的兴趣,因此在做了一些简单的DMEO,当然做DEMO难免遇到问题,特别是在做Session处理的时候 我使用redis来存储会话状态,设置中间件参数为: app.use(session({ store: new RedisStore(config.redisoption), secret: config.web.session_cookie_secret, resave: false, saveUninitialized: true, cookie:{expires: new Date(Date.now() +10000),maxAge: 10000} })); 关键点在设置cookie超时的问题上(上面我测试10秒超时),就是说session在建立后,如果我在10秒内没有向服务器发送消息,那么cookie自动清理,session会不存在,但是实际问题是:建立连接后,我在10秒内有请求给服务器,并且也做了req.session.save(),10秒后我的cookie仍然销毁了(请求后新产生了一个sessionid)。我也尝试过在我的请求后,手动res.cookie.expires = new Date(Date.now() +10000))修改超时时间,但仍然会在10秒后cookie销毁了,我在nodejs后台把每次请求的session显示处理,观察里面每次请求显示超时的时间也在变化(每次请求后,超时10秒起始计算时间会变化)。问题纠结了很久,请求各位大神们指导下。

untitled1.png


4 回复

我是nodejs小鸟,最近对nodejs产生了浓厚的兴趣,因此在做了一些简单的DMEO,当然做DEMO难免遇到问题,特别是在做Session处理的时候 我使用redis来存储会话状态,设置中间件参数为: app.use(session({ store: new RedisStore(config.redisoption), secret: config.web.session_cookie_secret, resave: false, saveUninitialized: true, cookie:{expires: new Date(Date.now() +10000),maxAge: 10000} })); 关键点在设置cookie超时的问题上(上面我测试10秒超时),就是说session在建立后,如果我在10秒内没有向服务器发送消息,那么cookie自动清理,session会不存在,但是实际问题是:建立连接后,我在10秒内有请求给服务器,并且也做了req.session.save(),10秒后我的cookie仍然销毁了(请求后新产生了一个sessionid)。我也尝试过在我的请求后,手动res.cookie.expires = new Date(Date.now() +10000))修改超时时间,但仍然会在10秒后cookie销毁了,我在nodejs后台把每次请求的session显示处理,观察里面每次请求显示超时的时间也在变化(每次请求后,超时10秒起始计算时间会变化)。问题纠结了很久,请求各位大神们指导下。

untitled1.png


帮顶等回复

当然可以!让我们一起来解决这个问题。首先,我们需要了解如何在 Node.js 中使用 express-sessionconnect-redis 来存储 session 数据到 Redis 中。

示例代码

假设你已经安装了必要的依赖包,如 express, express-session, connect-redisredis

npm install express express-session connect-redis redis

接下来,我们创建一个简单的 Express 应用程序,将 session 存储到 Redis 中:

const express = require('express');
const session = require('express-session');
const RedisStore = require('connect-redis')(session);
const redis = require('redis');

const app = express();
const client = redis.createClient({
    host: 'localhost',
    port: 6379
});

// 设置 session 中间件
app.use(session({
    store: new RedisStore({ client }),
    secret: 'your_secret_key',
    resave: false,
    saveUninitialized: true,
    cookie: {
        maxAge: 10000 // 10 秒
    }
}));

app.get('/', (req, res) => {
    req.session.views = (req.session.views || 0) + 1;
    req.session.save(err => {
        if (err) throw err;
    });
    res.send(`You have viewed this page ${req.session.views} times.`);
});

app.listen(3000, () => {
    console.log('Server is running on port 3000');
});

解释

  1. Redis 客户端:我们创建了一个 Redis 客户端实例,用于与 Redis 服务器通信。
  2. Session 中间件配置:我们使用 express-sessionconnect-redis 将 session 存储到 Redis 中。store 参数指定了 Redis 存储对象。
  3. Cookie 配置cookie.maxAge 指定了 session 的有效时间(在这个例子中是 10 秒)。

关于问题的解决

根据你的描述,你提到即使你在 10 秒内发送请求并且调用了 req.session.save(),cookie 仍然被销毁了。这可能是由于以下几个原因:

  1. Cookie 配置问题:确保你在客户端设置的 cookie 的 maxAgeexpires 是正确的。你可以通过浏览器开发者工具查看 cookie 的详细信息。
  2. Redis 配置问题:确保 Redis 服务器正确运行,并且 Express 应用能够成功连接到 Redis。
  3. 代码逻辑问题:确保你在每次请求时都正确地保存了 session。

调试建议

  • 在服务器端打印出每次请求的 session 信息,确保 session 正确保存。
  • 在浏览器端检查 cookie 是否正确设置。

希望这些信息能帮助你解决问题!如果有任何进一步的问题,请随时提问。

要解决你的问题,首先要理解express-session中间件的工作机制。它会根据配置的cookie.maxAge来决定Cookie的有效期。你提到的问题可能是因为每次请求后都会生成新的sessionID,这通常是因为saveUninitialized设置为true

下面是一个基本的配置示例,用于确保session能够正常持久化:

const session = require('express-session');
const RedisStore = require('connect-redis')(session);
const express = require('express');

const app = express();
const redisOption = {
    host: 'localhost',
    port: 6379,
};

app.use(session({
    store: new RedisStore({ client: redisOption }),
    secret: 'your_secret_key',
    resave: false,
    saveUninitialized: false, // 这里修改为false,避免每次请求都生成新的session
    cookie: { maxAge: 10000 }, // 设置超时时间
}));

app.get('/', (req, res) => {
    req.session.visits = (req.session.visits || 0) + 1;
    res.send(`Visits: ${req.session.visits}`);
});

app.listen(3000, () => console.log('Server is running on port 3000'));

在这个示例中,我们设置saveUninitializedfalse,这意味着只有当session数据被修改时,才会保存到存储中。这样可以减少不必要的session更新,有助于保持session的稳定性。

另外,如果你需要在每次请求后更新maxAge,可以在每次请求中手动调用req.session.touch()方法,该方法会更新session的最后访问时间,并相应地更新maxAge。例如:

app.get('/', (req, res) => {
    req.session.visits = (req.session.visits || 0) + 1;
    req.session.touch(); // 更新session的最后访问时间
    res.send(`Visits: ${req.session.visits}`);
});

通过以上调整,你应该可以实现预期的功能,即session在有效期内不会因为频繁请求而被错误地销毁。

回到顶部