(一) 描述
当用户在 Web 应用程序中导航 ASP.NET 页时,ASP.NET 会话状态使您能够存储和检索用户的值。HTTP 是一种无状态协议。这意味着 Web 服务器会将针对页面的每个 HTTP 请求作为独立的请求进行处理。服务器不会保留以前的请求过程中所使用的变量值的任何信息。
ASP.NET 会话状态将来自限定时间范围内的同一浏览器的请求标识为一个会话,当每个用户首次与这台WWW服务器建立连接时,他就与这个服务器建立了一个Session,同时服务器会自动为其分配一个SessionID,用以标识这个用户的唯一身份。Session提供用于在该会话持续期间内保留变量值的方法。默认情况下,将为所有 ASP.NET 应用程序启用ASP.NET 会话状态.
会话变量可以是任何有效的 .NET Framework 类型, 注意:当使用 InProc 以外的会话状态模式时,会话变量类型必须为基元 .NET 类型或可序列化的类型。这是因为会话变量值存储在外部数据存储区中。
会话由一个唯一标识符标识,可使用 SessionID 属性读取此标识符。为 ASP.NET 应用程序启用会话状态时,将检查应用程序中每个页面请求是否有浏览器发送的 SessionID 值。如果未提供任何 SessionID 值,则 ASP.NET 将启动一个新会话,并将该会话的 SessionID 值随响应一起发送到浏览器。
默认情况下,SessionID 值存储在 Cookie 中。但也可以将应用程序配置为在“无 Cookie”会话的 URL 中存储 SessionID 值。只要一直使用相同的 SessionID 值来发送请求,会话就被视为活动的。如果特定会话的请求间隔超过指定的超时值(以分钟为单位),则该会话被视为已过期。使用过期的 SessionID 值发送的请求将生成一个新的会话。
安全说明:
无论是作为 Cookie 还是作为 URL 的一部分,System.Web.SessionState.HttpSessionState.SessionID 值都以明文的形式发送。恶意用户通过获取 SessionID 值并将其包含在对服务器的请求中,可以访问另一位用户的会话。如果您将敏感信息存储在会话状态中,建议使用 SSL 来加密浏览器和服务器之间包含 SessionID 值的任何通信。
默认情况下,SessionID 值存储在浏览器的不过期会话 Cookie 中。但是,通过在 Web.config 文件的 sessionState 节中将 cookieless 属性设置为 true,可以指定不应将会话标识符存储在 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
(二)配置会话状态
通过使用 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 以提供对会话变量的只读访问。
注意:timeout是指会话的时间,单位是分钟,也就是如果客户端在timeout的时间内没有向服务器放送过请求,会话终止,所有的session数据将丢失。
(三)会话模式
ASP.NET 会话状态支持若干用于会话数据的存储选项。每个选项都由 SessionStateMode 枚举中的一个值标识。下面的列表描述了可用的会话状态模式:
InProc 模式,此模式将会话状态存储在 Web 服务器上的内存中。这是默认设置。
StateServer 模式,此模式将会话状态存储在一个名为 ASP.NET 状态服务的单独进程中。这确保了在重新启动 Web 应用程序时会保留会话状态,并让会话状态可用于网络场中的多个 Web 服务器。
SQLServer 模式将会话状态存储到一个 SQL Server 数据库中。这确保了在重新启动 Web 应用程序时会保留会话状态,并让会话状态可用于网络场中的多个 Web 服务器。
Custom 模式,此模式允许您指定自定义存储提供程序。
Off 模式,此模式禁用会话状态。
通过在应用程序的 Web.config 文件中为 sessionState 元素的 mode 属性分配一个 SessionStateMode 枚举值,可以指定要让 ASP.NET 会话状态使用的模式。除了 InProc 和 Off 之外,其他模式都需要附加参数,例如将在本主题后面讨论的连接字符串值。通过访问 HttpSessionStateMode 属性的值,可以查看当前选定的会话状态。
(四)示例
1. Login.aspx
<!----><%@ Page Language="C#" AutoEventWireup="true" CodeFile="Login.aspx.cs" Inherits="Login" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Button ID="mLoginButton" runat="server" Text="Login"
onclick="mLoginButton_Click" />
</div>
</form>
</body>
</html>
Login.aspx.cs
public partial class Login : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void mLoginButton_Click(object sender, EventArgs e)
{
Session["loginName"] = "Jack Wang" + DateTime.Now.ToString();
Response.Redirect("Default.aspx");
}
}
2. Default.aspx页
<!----><%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "
http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Session Sample</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Button ID="mGetSessionButton" runat="server" Text="Get Session"
onclick="mGetSessionButton_Click" />
<asp:Label ID="mShowSessionContentLabel" runat="server"></asp:Label>
</div>
</form>
</body>
</html>
Default.aspx.cs
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//Response.AddHeader("Refresh", (Session.Timeout*1000).ToString() + ";URL=Login.aspx");
if (string.IsNullOrEmpty(Session["loginName"] as string))
{
Response.Redirect("Login.aspx");
}
}
protected void mGetSessionButton_Click(object sender, EventArgs e)
{
mShowSessionContentLabel.Text = "<br> Now is:" + DateTime.Now.ToString() + "<br>Session Content:" +
Session["loginName"] as string + "<br>SessionId:" + Session.SessionID.ToString()
+"<br>session start time:"+ Session["startTime"] as string;
}
3. 示例不同的模式,配置web.config
a. InProc模式
<sessionState mode="InProc" timeout="2"></sessionState>
(1) 测试页面 ,过两分钟后再点击Get Session将返回到Login.aspx页,因为session过期
(2)重启web服务,点击Get Session将返回到Login.aspx页,因为session丢失
b. StateServer模式
注意:如果模式设置为 StateServer,则存储在会话状态中的对象必须是可序列化的。
(1)启动ASP.NET State Service服务
(2)修改SessionState为如下
<sessionState mode="StateServer" timeout="10"stateConnectionString="tcpip=127.0.0.1:42424">
</sessionState>
(3)重启web服务器,点击GetSession,session 10分钟内不会丢失,因为session存储服务器的另一个aspnet_state的进程里
c. sql server模式
描述:
如果是 SQL Server 模式,则存储在会话状态中的对象必须是可序列化的
默认情况下,Aspnet_regsql.exe 工具将创建一个名为 ASPState 的数据库,该数据库包含支持 SQLServer 模式的存储过程。默认情况下,会话数据本身存储在 tempdb 数据库中。您可以选择使用 -sstype 选项来更改会话数据的存储位置。下表给出了 -sstype 选项可能的值:
t :将会话数据存储到 SQL Server tempdb 数据库中。这是默认设置。如果将会话数据存储到 tempdb 数据库中,重新启动 SQL Server 时将丢失会话数据。
p:将会话数据存储到 ASPState 数据库中,而不是存储到 tempdb 数据库中。
c :将会话数据存储到自定义数据库中。如果指定 c 选项,则还必须使用 -d 选项包括自定义数据库的名称。
(1) 进入visual studio 2008(2005) command prompt
(2) 输入如下红色的命令
(3) 创建出如下数据库和表
(4) 运行页面,然后重启web服务,点击Get Session,session不会丢失,因为session保存到sql server数据库里了。