req.session.user 在用户处于活动状态时被删除
req.session.user is deleted while user is active
我将会话超时设置为 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>.... }
然后我阅读了一些有关 express-session 调用的 touch
方法的内容。文档说如果store实现了这个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,\"path\":\"/\"},\"user\":{\"email\":\"test@email.com\",\"sessionId\": \"some session id\"}}"
然后 30 分钟后,我查看了 redis,会话密钥仍然存在,但它停止递增到期时间。同时,req.session 仍会增加到期时间,但会删除用户 属性。
Why is req.session.user deleted after 30 minutes?
因为cookie的maxAge
选项设置为1800000
毫秒,也就是30分钟。因此浏览器(或您使用的任何客户端)将在 30 分钟后删除 cookie。
会话是您希望在后续请求中保留的一些信息。通常,一个会话有一个 ID(sessionID) 和关联的负载。当您执行 req.session = { ... }
时,express-session
中间件将获取对象,生成一个 ID 并将其保存在您指定的 store
中。 (RedisStore
在你的情况下)。所以现在你的 "database" 有 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
映射,它将根据 store
.
的 ttl
配置被删除
我认为首先出现的混乱是因为 session.cookie
字段。由于 express-session
中间件,session.cookie
将始终存在。
如果您想查看请求中收到的实际 cookie,请尝试 cookie-parser
中间件。
我正在将示例代码附加到 tinker。 set-cookie
端点将设置 20 秒后过期的 cookie。 get-cookie
端点将获得 cookie
和 session
数据。
希望这会有所帮助!
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
选项。在 express-session
中设置 rolling: true
后,会话将为每个请求更新。并且用户将在 maxAge
理想时间后注销。
我更新了代码。
我将会话超时设置为 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>.... }
然后我阅读了一些有关 express-session 调用的 touch
方法的内容。文档说如果store实现了这个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,\"path\":\"/\"},\"user\":{\"email\":\"test@email.com\",\"sessionId\": \"some session id\"}}"
然后 30 分钟后,我查看了 redis,会话密钥仍然存在,但它停止递增到期时间。同时,req.session 仍会增加到期时间,但会删除用户 属性。
Why is req.session.user deleted after 30 minutes?
因为cookie的maxAge
选项设置为1800000
毫秒,也就是30分钟。因此浏览器(或您使用的任何客户端)将在 30 分钟后删除 cookie。
会话是您希望在后续请求中保留的一些信息。通常,一个会话有一个 ID(sessionID) 和关联的负载。当您执行 req.session = { ... }
时,express-session
中间件将获取对象,生成一个 ID 并将其保存在您指定的 store
中。 (RedisStore
在你的情况下)。所以现在你的 "database" 有 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
映射,它将根据 store
.
ttl
配置被删除
我认为首先出现的混乱是因为 session.cookie
字段。由于 express-session
中间件,session.cookie
将始终存在。
如果您想查看请求中收到的实际 cookie,请尝试 cookie-parser
中间件。
我正在将示例代码附加到 tinker。 set-cookie
端点将设置 20 秒后过期的 cookie。 get-cookie
端点将获得 cookie
和 session
数据。
希望这会有所帮助!
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
选项。在 express-session
中设置 rolling: true
后,会话将为每个请求更新。并且用户将在 maxAge
理想时间后注销。
我更新了代码。