会话如何在 Express.js 和 Node.js 中工作?
Posted
技术标签:
【中文标题】会话如何在 Express.js 和 Node.js 中工作?【英文标题】:How do sessions work in Express.js with Node.js? 【发布时间】:2011-07-28 04:18:30 【问题描述】:使用Express.js,会话非常简单。不过我很好奇它们实际上是如何工作的。
它会在客户端上存储一些 cookie 吗?如果是这样,我在哪里可以找到那个 cookie?如果需要,如何解码?
我基本上希望能够查看用户是否已登录,即使该用户当时实际上并不在网站上(例如当您在其他网站上时 facebook 如何知道您已登录)。但我想了解我应该首先了解会话是如何工作的。
【问题讨论】:
【参考方案1】:概述
Express.js 使用 cookie 将会话 ID(带有加密签名)存储在用户的浏览器中,然后在后续请求中,使用该 cookie 的值来检索存储在服务器上的会话信息。此服务器端存储可以是内存存储(默认)或任何其他实现所需方法的存储(如connect-redis)。
详情
Express.js/Connect 使用 utils.uid(24)
创建一个 24 个字符的 Base64 字符串并将其存储在 req.sessionID
中。然后将该字符串用作 cookie 中的值。
客户端
签名 cookie 总是用于会话,因此 cookie 值将具有以下格式。
[sid].[signature]
其中 [sid] 是 sessionID,[signature] 是通过使用初始化会话中间件时提供的密钥对 [sid] 进行签名生成的。 签名步骤是为了防止篡改。在不知道使用的密钥的情况下修改 [sid] 然后重新创建 [签名] 在计算上应该是不可行的。如果不需要修改 [sid],会话 cookie 仍然容易被盗用和重复使用。
这个cookie的名字是
connect.sid
服务器端
如果处理程序出现在cookieParser
和session
中间件之后,它将可以访问变量req.cookies
。这包含一个 JSON 对象,其键是 cookie 键,值是 cookie 值。这将包含一个名为 connect.sid
的密钥,其值将是签名的会话标识符。
这是一个如何设置路由的示例,该路由将在每个请求上检查会话 cookie 的存在并将其值打印到控制台。
app.get("/*", function(req, res, next)
if(typeof req.cookies['connect.sid'] !== 'undefined')
console.log(req.cookies['connect.sid']);
next(); // Call the next middleware
);
您还需要确保在配置部分的cookieParser
和session
之后包含路由器 (app.use(app.router)
)。
以下是 Express.js/Connect 内部存储的数据示例。
"lastAccess": 1343846924959,
"cookie":
"originalMaxAge": 172800000,
"expires": "2012-08-03T18:48:45.144Z",
"httpOnly": true,
"path": "/"
,
"user":
"name":"waylon",
"status":"pro"
user
字段是自定义的。其他一切都是会话管理的一部分。
示例来自 Express 2.5。
【讨论】:
使用 console.log 打印 cookie 值时,它会给出编码(签名)的 cookie。如何获取真实信息? 你是什么意思--“如果不需要修改 [sid],会话 cookie 仍然容易被盗用和重用。”?既然 SID 是由 express 生成的,我们永远不能改变它吧? @WebHrushi 我在考虑中间人攻击:en.wikipedia.org/wiki/Man-in-the-middle_attack 有人可以帮我解决这个问题吗:***.com/questions/21982791/… 我如何为任何特定的 session_id 创建一个令牌??【参考方案2】:我从未使用过 Express.js,尽管根据 their documentation 的说法,它听起来像:
Cookie 存储在客户端上,带有一个密钥(服务器将使用它来检索会话数据)和一个哈希值(服务器将使用它来确保 cookie 数据没有被篡改,因此,如果您尝试更改值,则 cookie 将无效)
与某些框架(例如Play Framework!)相反,会话数据保存在服务器上,因此 cookie 更像是会话的占位符,而不是实际会话数据的持有者。
从 here 看来,服务器上的会话数据默认保存在内存中,尽管可以将其更改为实现适当 API 的任何存储形式。
因此,如果您想在没有特定 req
请求对象的情况下检查内容,就像您说的那样,您只需要访问相同的存储即可。在第一个文档页面的底部,它详细说明了存储需要实现的所需方法,因此,如果您熟悉存储 API,也许您可以执行 .getAll()
(如果存在类似的东西),并循环访问会话数据并读取您想要的任何值。
【讨论】:
【参考方案3】:我很好奇它们实际上是如何工作的。
尝试查看this 的答案和wiki 的东西。
它会在客户端存储一些cookie吗?
是的,它通常是一个带有指定会话 ID 的 cookie,应该使用秘密签名以防止伪造。
如果是这样,我在哪里可以找到那个 cookie?如果需要,如何解码?
您不应该在客户端使用会话 cookie。如果您想在服务器端使用会话,您应该查看相关的 express.js 和 connect 文档。
【讨论】:
【参考方案4】:除了已经很出色的答案,这里有 2 个图表,用于解释 Express 会话,它们与 cookie 和存储的链接:
巧克力饼干: 草莓曲奇:图表说明:
每个 cookie 都有独特的“风味”(或
sessionId
)。当草莓 cookie 呈现给服务器时(在 HTTP 请求中),服务器会识别这种风味并从存储中加载相应的数据:Rosie 的数据,并填充req.session
。
【讨论】:
很抱歉,我没有从图中得到任何信息。你想用/在其中传达什么? @RafaelSofi-zada 每个 cookie 都有独特的“风味”(或sessionId
)。当草莓 cookie 被呈现给服务器(通过 HTTP 请求)时,服务器会识别这种风味并从存储中加载相应的数据:Rosie 的数据,并使用 ! 填充req.session
以上是关于会话如何在 Express.js 和 Node.js 中工作?的主要内容,如果未能解决你的问题,请参考以下文章
node.js + express.js:使用 mongodb/mongoose 处理会话