【问题标题】:How does ASP.NET server know when a session is terminated?ASP.NET 服务器如何知道会话何时终止?
【发布时间】:2014-09-07 01:37:17
【问题描述】:

我了解 Session 对象用于存储每个会话的数据。我做了以下实验:

  1. 打开浏览器,访问一个aspx页面A,其中保存了一些数据到Session对象中。
  2. 保持浏览器打开并打开另一个选项卡以访问显示会话数据的 aspx 页面 B。它的显示方式与我在第 1 步中存储的一样。
  3. 我关闭浏览器重新访问页面B,存储的数据不见了。

从 3 开始,似乎服务器端以某种方式检测到我(客户端)已终止会话。但是当我检查 Fiddler 时,当我在步骤 3 中关闭浏览器时,没有任何位发送到服务器。

那么 ASP.NET 应用程序怎么可能知道我的第 3 步请求是针对新会话的呢?

会话是如何定义的?不同的标签是否总是属于同一个会话?

添加 1

虽然可以在页面A和页面B中显示会话数据,但是它们显示的会话ID是不同的。为什么?

正确

页面 A 和页面 B 中的会话 id 相同。我没有使用 InPrivate 浏览。

添加 2

确实有一个用于会话 ID 的 Cookie:

ASP.NET_SessionId=lmswljirqdjxdfq3mvmbwroy; path=/; domain=localhost; HttpOnly

在响应 POST 请求时设置。

所以我做了另一个实验,我关闭了浏览器(Fire Fox),正如预期的那样,Cookie 不再存在。我手动创建了 cookie,希望“伪造的 Cookie 可以恢复旧会话。”但 Fiddler 表示根本没有发送手动 cookie。

提琴手说:

This request did not send any cookie data.

那么是否可以伪造 cookie 并恢复之前的会话?

会话在服务器上存在多长时间?

【问题讨论】:

  • 您是否使用基于 cookie 的会话?您是否在使用某种隐私浏览?因为你描述的不是标准行为。假设您使用的是一个浏览器,会话在选项卡之间是持久的,并且浏览器正在打开和关闭,但前提是您使用的是 cookie 会话。除非您从正确的 URL 开始,否则使用任何其他类型(例如 URL 附加)都会导致您在每次访问时生成新会话。
  • @siva.k 不是标准行为吗?通常 asp.net 会话依赖于会话 cookie。当浏览器关闭时它们会被丢弃,但如果您关闭标签,它们会被保留(这就是为什么强烈建议您在关闭标签之前从网站注销,另请参阅this post about Chrome and its session management on crashes)。在服务器上,它们将超时过期
  • @AdrianoRepetti cookie 在您关闭窗口时不会丢弃(假设不是私密的)。当您打开浏览器备份时,它会将最后一组 cookie 发送回站点。否则,您加载的每个页面都需要您在每次关闭和打开浏览器时重新登录。使用基于 cookie 的会话可确保客户端始终尝试将其标识符发送回服务器。如果没有此 cookie,服务器将始终将请求视为新会话。是的,会话 cookie 是标准行为,但 smwikipedia 所描述的不是。
  • "通常asp.net会话依赖于会话cookie"。当然,我说的是会话 cookie! AFAIK OP 所描述的是我看到的每个浏览器中的标准行为。会话 cookie 跨选项卡共享,并在窗口关闭时丢弃。

标签: asp.net session state-management


【解决方案1】:

当服务器启动一个新会话时,它会为该会话生成一个新标识符。会话数据存储在会话提供程序中的此标识符/键下(可以是内存中、SQL Server 或其他完全取决于您的配置的东西 - 这通常在 web.config 中配置)。

同时,服务器会向您的浏览器发送一个 cookie(至少在默认设置中)。此 cookie 包含您的会话的标识符。这就是服务器如何将您的请求与您的特定会话相关联:在每个请求中,您的浏览器都会发送会话 cookie。服务器从 cookie 中检索标识符并使​​用该标识符查找您的会话数据。

会话cookie是非持久的,这意味着当浏览器关闭时cookie会被删除。这就是为什么looks like会话被删除的原因:会话数据仍然存在于服务器上,但是由于会话cookie已被删除,浏览器不会发送会话cookie,因此服务器会认为这是新会话的开始,创建新的会话标识符等。因此,服务器并不真正知道会话何时结束,它只知道会话何时开始。这就是为什么在默认 SQL Server 支持的设置中,计划作业将清除非活动会话 - 否则会话数据将永远留在数据库中。

有关会话、使用不带 cookie 的会话、会话配置、提供程序等的更多信息,请参阅MSDN

关于会话是否在浏览器选项卡之间共享:这实际上归结为 cookie 是否在选项卡之间共享。我认为 cookie 在所有主要浏览器的标签之间共享,我认为如果不是这样会很混乱,但是没有什么能阻止人们创建一个不跨标签共享 cookie 的浏览器。

编辑 1

如果您删除会话 cookie,理论上您可以通过重新创建 cookie 来重新创建会话。这本身不是安全问题,因为您正在重新创建您已经可以访问的数据。但是,如果其他人要重新创建您的会话 cookie,那将是一个安全问题。如果您想对此进行调查,可以搜索“ASP.NET 会话劫持”。

编辑 2

会话基本上存在于服务器上,直到有东西清除它。因此,会话的生命周期取决于您存储它的位置。如果你把它存储在内存中,当应用程序被回收时,会话将被删除(可能是因为你在 IIS 中回收了应用程序,也可能是因为服务器重新启动)。如果将其存储在 SQL Server 中,会话数据将一直存在,直到作业将其删除,因为它已经有一段时间没有被访问了(对不起,我不记得细节,但你可能可以用谷歌搜索它们)。如果将会话数据存储在 Azure 表存储中,它们可能永远不会被清除。

注意

ASP.NET 会话状态的两个重要细节经常被忽视:

  1. 当会话存储在进程之外(例如,在 SQL Server 中)时,您要存储的数据必须是可序列化的。
  2. 为了防止访问会话数据时出现竞争条件,访问会话的请求将被序列化,即它们不会并发执行。

更多详情请见the MSDN article "Underpinnings of the Session State Implementation in ASP.NET"

【讨论】:

  • @smwikipedia 在这个答案中有一个非常全面的文章的链接。它将回答您添加到问题中的所有后续问题
【解决方案2】:

本文提供了有关 ASP.NET 会话 (http://msdn.microsoft.com/en-us/library/vstudio/ms178581(v=vs.100).aspx) 的更多详细信息

这个想法很简单。

  1. 当您访问一个页面时,会生成一个会话 ID 并将其设置为 cookie。也会为该会话 ID 启动一个计时器。
  2. 当您不断返回时,计时器会重置。如果您在请求另一个页面之前等待足够长的时间,则计时器将到期并且您的会话将无效。此时将生成一个新会话。

回答您的问题: 如果您打开多个选项卡,它们将“共享”会话。因为您的浏览器正在从所有这些选项卡发送会话 cookie。 但是,如果您打开 Firefox 和 Chrome。这两个浏览器不会共享会话。因为,他们不共享 cookie。

当您关闭浏览器时,您的会话仍然有效。如果您在会话过期之前访问网站上的页面,您将不会获得新的会话。因此,建议始终注销。这样,网站就知道您要离开了,它会代表您销毁会话。

Q:虽然页面A和页面B可以显示会话数据,但是它们显示的会话ID是不同的。 答:你确定吗?所有页面的会话 ID 应该相同。如果您从一个浏览器访问页面 A,而从另一个浏览器访问页面 B,则会有所不同。

添加2

您的浏览器设置可能是在关闭窗口时销毁 cookie。请仔细检查选项中是否设置为记住历史记录。

Cookie 可以伪造。如果攻击者可以获取会话 ID,他们就可以在他们的最后伪造一个 cookie。我不确定 Fiddler 是否允许您手动创建 cookie。您将需要深入研究文档。或者也许这里的其他人可以回答这个问题。

【讨论】:

  • 页面A和B的会话ID相同。我更新了我的问题。
猜你喜欢
  • 2015-08-13
  • 2011-07-16
  • 1970-01-01
  • 2019-08-16
  • 1970-01-01
  • 1970-01-01
  • 2012-10-20
  • 2017-05-06
  • 1970-01-01
相关资源
最近更新 更多