何时在快速会话中使用 saveUninitialized 和重新保存

Posted

技术标签:

【中文标题】何时在快速会话中使用 saveUninitialized 和重新保存【英文标题】:When to use saveUninitialized and resave in express-session 【发布时间】:2017-03-15 20:25:53 【问题描述】:

我是 MEAN 堆栈的新手。我阅读了快速会话github doc,但有些选项我不清楚。这些选项是saveUninitializedresave

谁能用例子解释一下使用saveUninitializedresave有什么好处,如果我们改变这些选项中的布尔值会有什么影响。

语法:-

app.use(session(
  resave: false,
  saveUninitialized: true,
))

【问题讨论】:

【参考方案1】:

假设会话是全局启用的(对于所有请求)。

当客户端发出 HTTP 请求并且该请求不包含会话 cookie 时,express-session 将创建一个新会话。创建一个新会话会做一些事情:

生成唯一的会话 ID 将该会话 ID 存储在会话 cookie 中(以便可以识别客户端发出的后续请求) 创建一个空会话对象,如req.session 取决于saveUninitialized 的值,在请求结束时,会话对象将存储在会话存储中(通常是某种数据库)

如果在请求的生命周期内会话对象没有被修改,那么在请求结束并且saveUninitializedfalse 时,(仍然为空,因为未修改)会话对象不会存储在会话存储中。

这背后的原因是,这将防止在会话存储中存储大量空会话对象。由于没有什么有用的东西可以存储,会话在请求结束时被“遗忘”。

您希望何时启用此功能?例如,当您希望能够识别重复访问者时。您可以识别出这样的访问者,因为他们发送了包含唯一 ID 的会话 cookie。

关于resave:这可能需要为不支持“touch”命令的会话存储启用。它的作用是告诉会话存储一个特定的会话仍然处于活动状态,这是必要的,因为一些存储会在一段时间后删除空闲(未使用)的会话。

如果会话存储驱动程序没有实现触摸命令,那么您应该启用resave,这样即使会话在请求期间没有更改,它仍然会在存储中更新(从而将其标记为活动) .

因此,是否需要启用此选项完全取决于您使用的会话存储。

【讨论】:

我有些疑惑,可以谈谈吗,对我有很大帮助吗? @SurajJain 给我发一封关于 robert AT klep DOT 名称的电子邮件:D 这是一个很好的答案。感谢您花时间编写它。 什么是“触摸”命令?你说的这个会话存储是在客户端还是服务器端? Redis 需要重新保存吗?【参考方案2】:

需要注意的一点是,如果您将saveUninitialized 设置为false,除非会话被修改,否则不会在浏览器上设置会话cookie。这种行为可能是隐含的,但当我第一次阅读documentation 时,我并不清楚。

【讨论】:

哇,这似乎对我有所帮助。谢谢。我正在为类似按钮发出发布请求,并将 req.sessionID 保存到数据库中。无论如何,每当我单击按钮时,我都会得到一个新的 req.SessionID。这是一个可怕的时刻。无论如何。当我为发布请求执行处理程序时,我添加了req.session.liked = id,现在我没有得到新的会话ID。希望这解决了我的问题。 但是如果 'saveUninitialized' 设置为 "TRUE' 但会话没有被修改怎么办。我知道会话将保存在存储中,但会话 cookie 是否设置?跨度> 【参考方案3】:

on saveUninitialized set true 服务器会为浏览器提供会话 cookie 并将其保存在其内存中,即使您没有对会话对象进行任何修改。但是当后面的字段设置为false时,服务器只会在您修改会话对象时提供会话cookie,如果您已经有了会话cookie,那么不用担心!!

【讨论】:

【参考方案4】:

resave:这基本上意味着对于服务器的每个请求,它都会重置会话cookie。即使请求来自同一用户或浏览器,并且在请求期间从未修改过会话。

saveUninitialized:当创建一个空的会话对象并且没有设置任何属性时,它是未初始化的状态。因此,将 saveUninitialized 设置为 false 将不会保存未修改的会话。

resavesaveUninitialized 的默认值都是 true,但不推荐使用默认值。所以,根据用例设置合适的值。

【讨论】:

【参考方案5】:

我得出一个结论:

1.当您将saveUninitialized 设置为false 时,如果您创建的会话对象没有被修改即留空,那么您将无法在浏览器cookie 上看到connect.sid。这最终会迫使您的商店不存储会话对象,因为它尚未被修改,即未初始化。 true 反之亦然。

例如:

const express = require('express');
const dotenv = require("dotenv").config();
const app = express();
const session = require("express-session");
app.use(session(
  secret:"cat",
  resave:false,
  saveUninitialized:false,
  cookie:httpOnly:true
));
app.get('/login',(req,res)=>
  // req.session.user="sundar";
  // req.session.admin=true;
  console.log(req.sessionID);
  res.send(req.session.user);
)

app.post("/upload",(req,res)=>
  console.log(req.session);
  if (req.session.user === "sundar") 
    res.send("uploaded" + req.session.user)
  else
    res.send("failed");
  
  
)

app.listen(process.env.PORT, () => 
  console.log(`Listening on http://localhost:$process.env.PORT`);
);

在此示例中,如果您从邮递员或浏览器中点击/login,并且如果您查看 cookie,您将无法看到 connect.id,因为创建的会话对象未被修改。

但是如果你将/login修改为:

app.get('/login',(req,res)=>
   req.session.user="sundar";
   req.session.admin=true;
/* here we modified session object by adding user and admin properties to object created */
  res.send(req.session.user);
)

因此,您可以看到在浏览器或邮递员 cookie 部分设置了 connect.id cookie。这也意味着如果您有一个与会话中间件连接的存储,现在您的会话将存储在存储中。

    如果您将resave 设置为true,那么对于每个请求,您的会话cookie 每次都会被重置。参考:click here to read

【讨论】:

【参考方案6】:
    未初始化 = 假 这意味着只有在 req.session 中修改了任何属性时,您的会话才会存储到您的存储中 未初始化 = true 这意味着您的会话每次都将存储到您的存储中以供请求。不会依赖req.session的修改。 重新保存 = 真 这意味着当对会话执行修改时,它将重新写入 req.session.cookie 对象。 重新保存 = 假 它不会重写 req.session.cookie 对象。最初的 req.session.cookie 保持原样。

【讨论】:

以上是关于何时在快速会话中使用 saveUninitialized 和重新保存的主要内容,如果未能解决你的问题,请参考以下文章

何时在无状态会话 bean 上使用有状态会话 bean?

何时关闭休眠会话?

php - 会话变量何时保存?

在 JSF 登录期间何时创建会话?

何时以及如何正确停用您的音频会话?

Rails 如何知道何时从 `sessions` 表中删除记录?