当用户处于活动状态时,req.session.user被删除

时间:2018-11-08 09:34:04

标签: node.js passport.js node-redis

我将会话超时设置为30分钟。在我仍处于活动状态时,req.session.user在30分钟后被删除。但是,该会话仍然有效。这是我的配置(我正在使用express-session和passport.js):

app.use(session({
    store: new RedisStore({client: <my client>, disableTTL: true}),
    secret: <some_secret>,
    resave: true,
    saveUninitialized: false,
    cookie: {maxAge: 1800000}
}));

app.use(passport.initialize());
app.use(passport.session());

// Are these serializer/deserializer needed?
passport.serializeUser((user, done) => {
    done(null, user);
});
passport.deserializeUser((user, done) => {
    done(null, user);
});

登录时:

router.post('/login', (req, res, next) => {
    passport.authenticate('ldapauth', {session: false}, (err, user, info) => {
        ...
        if (user) {
            req.session.user = {email: req.body.username};
        }
        next();
    })(req, res);
});

验证码如下:

isLoggedIn() {
    if (req.session && req.session.user) {
        return true;
    }
    return false;
}

成功登录后,我将req.session.user设置为某个对象。

因此,在30分钟之后,req.session.user被删除,但是req.session仍然存在,并且由于我仍在积极地从事该页面的工作,因此会继续增加有效期。

为什么req.session.user在30分钟后被删除?我以为护照是通过快递搭的?

*更新* 起初,我以为到期日在增加,但事实并非如此。以前,我设置了resave: false。然后,当我记录会话时,有效期总是相同的:

Session {
    cookie:
         { path: '/', _expires: <some date>.... }
    user:
         { email: <the one i set before>, sessionId: <some id> } }

然后在30分钟后删除用户。仅在这一点上,到期时间开始增加。

Session {
    cookie:
         { path: '/', _expires: <some date>.... }

然后,我读了一些有关touch方法的快速会话调用的知识。文档说,如果商店实现此touch方法,则可以设置resave: false。因此,考虑到redis可能未实现此方法,我尝试设置resave: true。然后,当我记录会话时,我注意到到期现在正在增加,而以前的到期只是在删除用户之后才增加。但是,30分钟后,再次删除了用户密钥。

然后在niry的建议下,我设置了disableTTL: true。同样,同样的事情发生了。

在Redis中,我尝试匹配密钥。在30分钟结束之前,redis的到期日将递增:

127.0.0.1:6379> mget sess:<some id>

1)“ {\” cookie \“:{\” originalMaxAge \“:1800000,\” expires \“:\” 2018-11-15T06:04:26.994Z \“,\” httpOnly \“:true ,\“路径\”:\“ / \”},\“用户\”:{\“电子邮件\”:\“ test@email.com \”,\“ sessionId \”:\“某些会话ID \” }}“

然后,在30分钟后,我看着redis,会话密钥仍然存在,但是它停止增加有效期。虽然,req.session仍然会增加到期时间,但是删除了用户属性。

1 个答案:

答案 0 :(得分:0)

  

为什么30分钟后删除了req.session.user?

因为cookie的maxAge选项设置为1800000毫秒,即30分钟。因此,浏览器(或您使用的任何客户端)将在30分钟后删除Cookie。

会话是您要保留在后续请求中的一些信息。通常,会话具有ID(sessionID)和关联的有效负载。当您执行req.session = { ... }时,express-session中间件将获取对象,生成一个ID并将其保存在您指定的store中。 (在您的情况下为RedisStore)。因此,现在您的“数据库”具有sessionIDpayload的映射。

Cookie一旦从服务器发送出去,就会针对每个后续请求每次都转发到该服务器(到该域),直到它们过期为止。请注意,一旦收到cookie,就将由客户来管理它。生成的sessionID和签名一起通过Cookie发送到客户端。

一旦Cookie被保存在您的客户端上。它将与下一个请求一起转发。 当您的express-session中间件看到cookie时,它将从cookie中提取sessionID,并尝试在store(在您的情况下为RedisStore)中查找相应的有效负载。然后将有效负载以及其他信息设置为req.session

一旦到期,客户端将删除cookie。因此,来自该客户端的请求将没有cookie。由于cookie不存在,因此express-session将无法设置req.session,并且您会认为用户已注销。请注意,该存储区仍然包含sessionID, payload映射,它将根据ttl的{​​{1}}配置删除。


我认为首先引起的混乱是因为store字段。由于session.cookie中间件,session.cookie将一直存在。

如果您想查看请求中收到的实际cookie,请尝试使用cookie-parser中间件。


我正在将示例代码附加到修补程序。 express-session端点将设置cookie,该cookie将在20秒后过期。 set-cookie端点将获取get-cookiecookie数据。

希望这会有所帮助!

session

更新 根据评论,您正在寻找rolling选项。在const express = require("express"); const session = require("express-session"); const cookieParser = require("cookie-parser"); const FileStore = require("session-file-store")(session); const path = require("path"); const app = express(); app.use(express.json()); app.use(cookieParser()); app.use( session({ secret: "top secret!", resave: false, rolling: true, saveUninitialized: false, cookie: { maxAge: 20 * 1000 }, name: "demo", store: new FileStore({ path: path.join(__dirname, "../sessions"), retries: 1, fileExtension: ".json" }) }) ); app.use("/set-cookie", (req, res) => { req.session.payload = { foo: "bar", timestamp: new Date().toISOString() }; res.json({ message: "done" }); }); app.use("/get-cookie", (req, res) => { res.json({ sessionID: req.sessionID, session: req.session, cookies: req.cookies, timestamp: new Date().toISOString() }); }); app.listen(3000, err => { if (err) { throw err; } console.log("demo app listening on port 3000"); }); 中设置rolling: true后,会话将针对每个请求进行更新。并且用户将在express-session个理想时间之后退出。

我已经更新了代码。