会话如何在 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

服务器端

如果处理程序出现在cookieParsersession 中间件之后,它将可以访问变量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
);

您还需要确保在配置部分的cookieParsersession 之后包含路由器 (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 中工作?的主要内容,如果未能解决你的问题,请参考以下文章

React 前端 + Express.js 会话

没有 express.js 的 Socket.io 会话?

node.js + express.js:使用 mongodb/mongoose 处理会话

Node.js/Express.js 会话管理 cookie 为会话 cookie

从 Jade 模板访问 Express.js 请求或会话

Express.js/Passport 应用程序为每个请求创建新会话,尽管请求标头中有会话 ID