我将会话超时设置为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仍然会增加到期时间,但是删除了用户属性。
答案 0 :(得分:0)
为什么30分钟后删除了req.session.user?
因为cookie的maxAge
选项设置为1800000
毫秒,即30分钟。因此,浏览器(或您使用的任何客户端)将在30分钟后删除Cookie。
会话是您要保留在后续请求中的一些信息。通常,会话具有ID(sessionID)和关联的有效负载。当您执行req.session = { ... }
时,express-session
中间件将获取对象,生成一个ID并将其保存在您指定的store
中。 (在您的情况下为RedisStore
)。因此,现在您的“数据库”具有sessionID
和payload
的映射。
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-cookie
和cookie
数据。
希望这会有所帮助!
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
个理想时间之后退出。
我已经更新了代码。