ASP.NET服务器如何知道会话何时终止?

3
我知道Session对象用于每个会话存储数据。我做了以下实验:
  1. 打开浏览器并访问一个保存数据到Session对象的aspx页面A。
  2. 保持浏览器打开,并打开另一个选项卡访问显示会话数据的aspx页面B。它显示的数据与我在步骤1中存储的一样。
  3. 我关闭浏览器并重新访问页面B,存储的数据消失了。
从第3点来看,似乎服务器端会检测到我(客户端)已终止会话。但是,当我在步骤3中关闭浏览器时,使用Fiddler进行检查时,没有任何比特发送到服务器。
那么ASP.NET应用程序如何知道我的第3步请求是一个新的会话呢?
会话是如何定义的?不同的选项卡是否总是属于同一个会话?
ADD 1
尽管会话数据可以在页面A和页面B中显示,但它们中显示的会话ID是不同的。为什么?
Correct
页面A和页面B中的会话ID是相同的。我没有使用InPrivate浏览。
ADD 2
确实有一个用于会话ID的Cookie:
ASP.NET_SessionId=lmswljirqdjxdfq3mvmbwroy; path=/; domain=localhost; HttpOnly

当POST请求得到响应时,它被设置。

于是我进行了另一个实验,关闭了浏览器(Fire Fox),预料之中,Cookie不再存在。我手动创建Cookie希望“伪造的Cookie能够恢复旧会话”,但Fiddler显示手动创建的Cookie根本没有被发送。

Fiddler提示:

This request did not send any cookie data.

那么,能否伪造一个cookie并恢复先前的会话?

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


你是否使用基于cookies的会话?你是否使用某种隐私浏览模式?因为你所描述的不是标准行为。假设你正在使用一个浏览器,会话在选项卡之间以及打开和关闭浏览器时是持久的,但前提是你使用cookie会话。如果使用其他类型,例如URL附加,除非你从正确的URL开始,否则每次访问都会生成新的会话。 - siva.k
@siva.k 这不是标准行为吗?通常 asp.net 会话依赖于会话 cookie。当浏览器关闭时,它们会被丢弃,但如果您关闭选项卡,则会保留它们(这就是为什么强烈建议在关闭选项卡之前注销网站,另请参见关于 Chrome 及其会话管理崩溃的帖子)。在服务器上,它们将因超时而过期。 - Adriano Repetti
@AdrianoRepetti,假设不是在隐私模式下,cookie在关闭窗口时不会被丢弃。当您重新打开浏览器时,它将向站点发送上次设置的cookie。否则,每次关闭和打开浏览器时,您加载的每个页面都需要重新登录。使用基于cookie的会话确保客户端始终尝试将其标识符发送回服务器。如果没有此cookie,则服务器将始终将请求视为新会话。是的,会话cookie是标准行为,但smwikipedia所描述的不是标准行为。 - siva.k
通常情况下,asp.net会话依赖于会话cookie。当然我在谈论会话cookie!据我所知,OP所描述的是我见过的每个浏览器中的标准行为。会话cookie在选项卡之间共享,并在关闭窗口时被丢弃。 - Adriano Repetti
2个回答

8
当服务器启动新会话时,会为该会话生成一个新的标识符。会话数据存储在此标识符/键下的会话提供程序中(根据您的配置可以是内存中、SQL Server中或完全不同的其他地方 - 这通常在web.config中配置)。
同时,服务器会向您的浏览器发送一个cookie(至少在默认设置中)。该cookie包含您会话的标识符。这就是服务器如何将您的请求与特定会话相关联的方式:在每个请求中,您的浏览器都会发送会话cookie。服务器从cookie中检索标识符,并使用标识符查找您的会话数据。
会话cookie是非持久性的,这意味着当关闭浏览器时,cookie将被删除。这就是为什么它“看起来像”会话已被删除的原因:会话数据仍然存在于服务器上,但由于会话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. 为了防止访问会话数据时出现竞争条件,访问会话的请求将被串行化,即它们不会并发执行。
更多细节可以在ASP.NET中会话状态实现的基础的MSDN文章中找到。

@smwikipedia 在这个答案中有一个链接到一个非常全面的文章。它将回答您在问题中添加的所有后续问题。 - Adriano Repetti

1
本文提供了关于ASP.NET Session(http://msdn.microsoft.com/en-us/library/vstudio/ms178581(v=vs.100).aspx)的更多细节。
这个想法很简单。
1. 当您访问一个页面时,会生成并设置一个会话ID作为cookie。该会话ID的计时器也会启动。 2. 随着您不断地回来,计时器会被重置。如果您在请求另一个页面之前等待足够长的时间,计时器将过期,您的会话将无效。此时将生成一个新的会话。
回答您的问题: 如果您打开多个选项卡,它们将“共享”会话。因为您的浏览器从所有这些选项卡发送会话cookie。 但是,如果您打开Firefox和Chrome。这两个浏览器将不共享会话。因为它们不共享cookie。
当您关闭浏览器时,您的会话仍然有效。如果在会话过期之前访问站点上的页面,则不会获得新会话。这就是为什么建议始终注销的原因。这样,站点就知道您正在离开,并将代表您销毁会话。

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

ADD2

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

Cookie可以被伪造。如果攻击者能够获取会话ID,则可以在其端伪造Cookie。我不确定Fiddler是否允许您手动创建Cookie。您需要查看文档。或者也许这里的其他人可以回答这个问题。


页面A和B的会话ID相同。我更新了我的问题。 - smwikipedia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接