ASP.NET 会话状态概述

更新:2007 年 11 月

可使用 ASP.NET 会话状态存储和检索用户的值。

本主题包括:

  • 背景

  • 代码示例

  • 类参考

背景

当用户在 Web 应用程序中导航 ASP.NET 页时,ASP.NET 会话状态使您能够存储和检索用户的值。HTTP 是一种无状态协议。这意味着 Web 服务器会将针对页面的每个 HTTP 请求作为独立的请求进行处理。服务器不会保留以前的请求过程中所使用的变量值的任何信息。ASP.NET 会话状态将来自限定时间范围内的同一浏览器的请求标识为一个会话,并提供用于在该会话持续期间内保留变量值的方法。默认情况下,将为所有 ASP.NET 应用程序启用 ASP.NET 会话状态。

会话状态的替代项包括:

  • 应用程序状态,存储 ASP.NET 应用程序的所有用户可访问的变量。

  • 配置文件属性,将用户值保留在数据存储区中,使它们不会过期。

  • ASP.NET 缓存,将值存储在所有 ASP.NET 应用程序可用的内存中。

  • 视图状态,将值保留在页面中。

  • Cookie。

  • 可通过 HTML 请求访问的 HTTP 窗体上的查询字符串和字段。

有关对不同的状态管理选项的比较,请参见 ASP.NET 状态管理建议

会话变量

会话变量存储在通过 HttpContext.Session 属性公开的 SessionStateItemCollection 对象中。在 ASP.NET 页中,当前会话变量将通过 Page 对象的 Session 属性公开。

会话变量集合按变量名称或整数索引来进行索引。可通过按照名称引用会话变量来创建会话变量,而无需声明会话变量或将会话变量显式添加到集合中。下面的示例演示如何在 ASP.NET 页上创建分别表示用户的名字和姓氏的会话变量,并将它们设置为从 TextBox 控件检索到的值。

Session("FirstName") = FirstNameTextBox.Text
Session("LastName") = LastNameTextBox.Text
Session["FirstName"] = FirstNameTextBox.Text;
Session["LastName"] = LastNameTextBox.Text;

会话变量可以是任何有效的 .NET Framework 类型。下面的示例将 ArrayList 对象存储在名为 StockPicks 的会话变量中。当从 SessionStateItemCollection 检索由 StockPicks 会话变量返回的值时,必须将此值强制转换为适当的类型。

' When retrieving an object from session state, cast it to 
' the appropriate type.
Dim stockPicks As ArrayList = CType(Session("StockPicks"), ArrayList)

' Write the modified stock picks list back to session state.
Session("StockPicks") = stockPicks
// When retrieving an object from session state, cast it to 
// the appropriate type.
ArrayList stockPicks = (ArrayList)Session["StockPicks"];

// Write the modified stock picks list back to session state.
Session["StockPicks"] = stockPicks;
ms178581.alert_note(zh-cn,VS.90).gif说明:

当使用 InProc 以外的会话状态模式时,会话变量类型必须为基元 .NET 类型或可序列化的类型。这是因为会话变量值存储在外部数据存储区中。有关更多信息,请参见会话状态模式

会话标识符

会话由一个唯一标识符标识,可使用 SessionID 属性读取此标识符。为 ASP.NET 应用程序启用会话状态时,将检查应用程序中每个页面请求是否有浏览器发送的 SessionID 值。如果未提供任何 SessionID 值,则 ASP.NET 将启动一个新会话,并将该会话的 SessionID 值随响应一起发送到浏览器。

默认情况下,SessionID 值存储在 Cookie 中。但也可以将应用程序配置为在“无 Cookie”会话的 URL 中存储 SessionID 值。

只要一直使用相同的 SessionID 值来发送请求,会话就被视为活动的。如果特定会话的请求间隔超过指定的超时值(以分钟为单位),则该会话被视为已过期。使用过期的 SessionID 值发送的请求将生成一个新的会话。

ms178581.alert_security(zh-cn,VS.90).gif安全说明:

无论是作为 Cookie 还是作为 URL 的一部分,P:System.Web.SessionState.HttpSessionState.SessionID 值都以明文的形式发送。恶意用户通过获取 SessionID 值并将其包含在对服务器的请求中,可以访问另一位用户的会话。如果您将敏感信息存储在会话状态中,建议使用 SSL 来加密浏览器和服务器之间包含 SessionID 值的任何通信。

默认情况下,SessionID 值存储在浏览器的不过期会话 Cookie 中。但是,通过在 Web.config 文件的 sessionState 节中将 cookieless 属性设置为 true,可以指定不应将会话标识符存储在 Cookie 中。

下面的示例演示一个 Web.config 文件,它将 ASP.NET 应用程序配置为使用无 Cookie 会话标识符。

<configuration>
  <system.web>
    <sessionState cookieless="true"
      regenerateExpiredSessionId="true" />
  </system.web>
</configuration>

ASP.NET 通过自动在页的 URL 中插入唯一的会话 ID 来保持无 Cookie 会话状态。例如,下面的 URL 已被 ASP.NET 修改,以包含唯一的会话 ID lit3py55t21z5v55vlm25s55:

http://www.example.com/(S(lit3py55t21z5v55vlm25s55))/orderform.aspx

当 ASP.NET 向浏览器发送页时,ASP.NET 将修改页中任何使用相对于应用程序的路径的链接,在链接中嵌入一个会话 ID 值。(不修改具有绝对路径的链接。)只要用户单击已按这种方式修改的链接,即可保持会话状态。但是,如果客户端重新写入应用程序提供的 URL,ASP.NET 将不能解析此会话 ID,也不能将请求与现有的会话相关联。在这种情况下,将为请求启动一个新的会话。

会话 ID 嵌入在 URL 中应用程序名称后的斜杠之后,在其余所有文件或虚拟目录标识符之前。这使 ASP.NET 可以在使用请求中的 SessionStateModule 之前解析应用程序的名称。

ms178581.alert_note(zh-cn,VS.90).gif说明:

为提高应用程序的安全性,您应当允许用户从应用程序注销,此时应用程序应当调用 Abandon 方法。这降低了恶意用户获取 URL 中的唯一标识符并用它检索存储在会话中的用户私人数据的风险。

重新生成已过期的会话标识符

默认情况下,将回收无 Cookie 会话中使用的会话 ID 值。也就是说,如果使用已过期的会话 ID 发起一个请求,将使用该请求提供的 SessionID 值启动一个新的会话。当包含无 Cookie SessionID 值的链接由多个浏览器使用时,这会导致无意中共享会话。(如果通过搜索引擎、电子邮件或另一个程序传递链接,则会发生这种情况。)可以通过将应用程序配置为不回收会话标识符来减少共享会话数据的机会。为此,将 sessionState 配置元素的 regenerateExpiredSessionId 属性设置为 true。这将在使用已过期的会话 ID 发起无 Cookie 会话请求时,生成一个新的会话 ID。

ms178581.alert_note(zh-cn,VS.90).gif说明:

如果通过使用 HTTP POST 方法发起已使用已过期会话 ID 发起的请求,则当 regenerateExpiredSessionId 为 true 时,将丢失发送的所有数据。这是因为 ASP.NET 会执行重定向,以确保浏览器在 URL 中具有新的会话标识符。

自定义会话标识符

可以实现自定义类来提供和验证 SessionID 值。为此,请创建一个从 SessionIDManager 类继承的类,并用您自己的实现来重写 CreateSessionIDValidate 方法。有关示例,请参见为 CreateSessionID 方法提供的示例。

可以通过创建实现 ISessionIDManager 接口的类来替换 SessionIDManager 类。例如,通过使用 ISAPI 筛选器,Web 应用程序可能将唯一标识符与非 ASP.NET 页(如 HTML 页或图像)相关联。可以实现自定义的 SessionIDManager 类,将此唯一标识符用于 ASP.NET 会话状态。如果您的自定义类支持无 Cookie 会话标识符,则必须实现一个解决方案以便在 URL 中发送和检索会话标识符。

会话模式

ASP.NET 会话状态支持会话变量的一些存储选项。每个选项都被标识为一个会话状态 Mode 类型。默认行为是将会话变量存储在 ASP.NET 辅助进程的内存空间中。不过,也可以指定是应将会话状态存储在单独进程、SQL Server 数据库还是自定义数据源中。如果不希望为应用程序启用会话状态,可以将会话模式设置为 Off

有关更多信息,请参见会话状态模式

会话事件

ASP.NET 提供两个可帮助您管理用户会话的事件:Session_OnStart 事件和 Session_OnEnd 事件。前者在开始一个新会话时引发;而后者在一个会话被放弃或过期时引发。会话事件是在 ASP.NET 应用程序的 Global.asax 文件中指定的。

如果将会话 Mode 属性设置为 InProc(默认模式)以外的值,则不支持 Session_OnEnd 事件。

ms178581.alert_note(zh-cn,VS.90).gif说明:

如果 ASP.NET 应用程序的 Global.asax 文件或 Web.config 文件被修改,将重新启动应用程序,而且存储在应用程序状态或会话状态中的所有值都将丢失。注意,某些防病毒软件可能会更新应用程序的 Global.asax 或 Web.config 文件的最后修改日期和时间。

有关更多信息,请参见会话状态事件

配置会话状态

通过使用 system.web 配置节的 sessionState 元素可配置会话状态。还可以通过使用 @ Page 指令中的 EnableSessionState 值来配置会话状态。

使用 sessionState 元素可指定以下选项:

  • 会话存储数据所使用的模式。

  • 在客户端和服务器间发送会话标识符值的方式。

  • 会话的 Timeout 值。

  • 支持基于会话 Mode 设置的值。

下面的示例演示一个 sessionState 元素,该元素将配置应用程序的 SQLServer 会话模式。该元素将 Timeout 值设置为 30 分钟,并指定将会话标识符存储在 URL 中。

<sessionState mode="SQLServer"
  cookieless="true "
  regenerateExpiredSessionId="true "
  timeout="30"
  sqlConnectionString="Data Source=MySqlServer;Integrated Security=SSPI;"
  stateNetworkTimeout="30"/>

可以通过将会话状态模式设置为 Off 来禁用应用程序的会话状态。如果只希望禁用应用程序的某个特定页的会话状态,则可以将 @ Page 指令中的 EnableSessionState 值设置为 false。还可将 EnableSessionState 值设置为 ReadOnly 以提供对会话变量的只读访问。

并发请求和会话状态

对 ASP.NET 会话状态的访问专属于每个会话,这意味着如果两个不同的用户同时发送请求,则会同时授予对每个单独会话的访问。但是,如果这两个并发请求是针对同一会话的(通过使用相同的 SessionID 值),则第一个请求将获得对会话信息的独占访问权。第二个请求将只在第一个请求完成之后执行。(如果由于第一个请求超过了锁定超时时间而导致对会话信息的独占锁定被释放,则第二个会话也可获得访问权。)如果将 @ Page 指令中的 EnableSessionState 值设置为 ReadOnly,则对只读会话信息的请求不会导致对会话数据的独占锁定。但是,对会话数据的只读请求可能仍需等到解除由会话数据的读写请求设置的锁定。

返回页首

代码示例

如何:保存会话状态中的值

如何:读取会话状态中的值

实现会话状态存储提供程序

返回页首

类参考

下表列出了与 System.Web.SessionState 命名空间中的会话状态相关的关键类。

成员

说明

SessionIDManager

管理 ASP.NET 会话状态的唯一标识符。

SessionStateItemCollection

用于存储会话状态变量。

返回页首

请参见

概念

实现会话状态存储提供程序