什么是Session?
web是无状态,这意味着每次页面被回传到服务器时,都重新生成一个web页面类的一个新的实例。
众所周知http时无状态的协议。它不能获得客户端的信息。如果用户录入了一些信息,当跳转到下一个页面时,数据丢失,再也不能获得那些数据。我们需要保存这些数据,Session提供了一种把这些信息保存在服务器内存中的一种方式。它能存储各种数据类型包括自定义对象。每个客户端的Session是独立存储。Session的优点和缺点是什么?
下面是session基本的优点和缺点,稍后我将详细描述。
优点 : * 能帮助我们在整个应用程序中维护用户状态. * 易于实现,能存储各种数据类型. * 每个客户端独立存储. * Session是安全的,对用户透明.缺点 : * 在大量用户情况下,系统开销太大。因为session保存在服务器内存中。 * 序列化和反序列化session中的数据开销大。因为在StateServer,SQLServer模式时,在保存前必须把对象序列化。Session数据的保存和读取
在session中保存和读取数据的方式和ViewState相似。我们使用System.Web.SessionState.HttpSessionState类交互Session状态。
在Session中保存数据- Session["UserName"] = txtUser.Text;
从Session中读取数据
- //检查session变量是否为空
- if (Session["UserName"] != null)
- {
- //从session返回username
- lblWelcome.Text = "Welcome : " + Session["UserName"];
- }
- else
- {
- //做别的事情
- }
我们session保存对象。下面显示怎么在session中保存DataSet对象
- //在session中保存dataset
- Session["DataSet"] = _objDataSet;
下面显示怎么从session读取那个dataset。
- //检查session变量是否为空
- if (Session["DataSet"] != null)
- {
- DataSet _MyDs = (DataSet)Session["DataSet"];
- }
- else
- {
- //做别的事情
- }
参考或更多的信息:
Session ID
Asp.net使用120位标志符来跟踪每个session,这足够安全不能逆向工程。当客户端和服务器通讯时,只有SessionID被传输。当客户端请求数据时,asp.net根据SessionID返回相应的数据。按照下列步骤进行:
* 客户端请求web站点,一些信息被存储在session中。 * 服务器为客户端生成一个唯一的Session id,存储数据在Session状态提供者中。 * 客户端带着这个SessionID向服务器请求数据。 * 服务器在Session提供者中找到Session ID.找出被序列化存储在服务器中的数据,进行类型转化。Session模式和状态提供者
在ASP.NET有下列Session模式
* InProc * StateServer * SQLServer * Custom 对于每个session模式,都有一个session提供者. 下列图将为你展示他们之间的关系。Session State Mode | State Provider |
---|---|
InProc | In-Memory Object |
StateServer | Aspnet_state.exe |
SQLServer | DataBase |
Custom | CustomProvider |
除了上边的,还有一种模式:“OFF”.如果你选择这个设置,Session将对应用程序无效。因为我们想使用session,所以我们主要关注那四种模式。
Session状态:
Session状态意味着我们需要为应用程序作些设置。要么在web.config中设置,要么在页面代码中设置。在web.config中SessionState节点是用来做配置的,如:session模式,超时,状态连接串,自定义提供者等。在讨论session模式前,先概述一下session事件。
Session 事件
在asp.net有两个事件:
* Session_Start * Session_End 你可以在web应用程序的global.asax文件中操作这两个事件。当一个新的session初始化时,触发session_start事件。当一个session过期时触发Session_End事件。- void Session_Start(object sender, EventArgs e)
- {
- // 当新的session产生时,这段代码运行
- }
- void Session_End(object sender, EventArgs e)
- {
- // 当新的session结束时,这段代码运行.
- }
Session模式
我已经讨论了ASP.NET中的session模式,下面是几种不同的模式:
* Off * InProc * StateServer * SQLServer * Custom 如果你在web.config设置了Session Mode="off".session将在这个应用程序中无效,你可以想下面的方式设置:- <system.web>
- <!-- Disable Session in Application -->
- <sessionState mode="Off"></sessionState>
- </system.web>
InPorc Session 模式
这是Asp.Net的缺省模式. 它存储session信息在当前的应用程序域中. 这是性能最好的模式. 最大的缺点是当应用程序重启时,session数据丢失。关于InPorc模式session优缺点后面再讨论。
概述:
由于存储session信息在当前的应用程序域中. 所以它易于操作,快速有效.InProc session存储数据在应用程序域的内存对象中,被应用程序池的工作进程操作。 所以当我们重启服务器时丢失Session数据。如果客户端请求这个数据,状态提供者从内存对象中读取,并返回客户端。在web.config文件中我们可以设置Session模式,超时等:
- <system.web>
- <!-- InProc Session in Application -->
- <sessionState mode ="InProc" timeout ="30"></sessionState>
- </system.web>
- Session.TimeOut=30;
在asp.net中,有两类Session事件:Session_Start() 和 Session_End;InProc session模式时唯一支持Session_End()的模式。这个事件将在Session超时期结束后被调用。一般session状态流动象下面这样:
Session_End()被调用依赖于Session超时,这是一个非常快速的机制,因为返回或存储数据不用序列化,数据一直存储在相同的应用程序域中什么时候我们该使用InProc Session模式?InProc 是缺省的模式,对小型的,用户数量比较少的网站非常有用。在web园场景中避免使用。优缺点有点 : * Session数据存储在当前应用程序域的内存对象中,所以访问快速。 * 对数据不需要序列化,和反序列化. * 实现简单,如同View State.缺点 : * 如果工作进程或应用程序域回收时,所有session数据丢失。 * 虽然他是最快速的,但当Session数据比较多,或用户比较多时比较影响性能。因为它使用的时内存。 * 在web园场景中不能使用. * 也不适合web农场场景.StateServer Session 模式
概述
这种也被称为进程外模式 StateServer使用一个独立的Windows Services。它不依赖IIS 也能运行于一个独立的服务器. 这种Session模式总的来说被aspnet_state.exe管理。StateServer可以和web应用程序使用同一个服务器,但是它在web应用程序域的外边。这就容许你即使重启了asp.net进程但session数据仍然是活动的。在命令行执行 "net start aspnet_state"启动. 缺省端口42424 , 可以通过注册表修改这个端口号,如下图:
现在让我们看看web.config关于StateServer的配置。stateConnectionString指定运行的的服务器。缺省ip:127.0.0.1 (localhost) 端口 42424。
- <system.web>
- <!-- StateServer Session in Application -->
- <sessionState mode ="StateServer"
- stateConnectionString ="tcpip=127.0.0.1:42424" />
- </system.web>
当我们使用StateServer时,可以配置stateNetworkTimeOut,用来指定在撤销请求前,可以等待StateServer响应的秒数。缺省10秒。
- <system.web>
- <!-- StateServer Session in Application -->
- <sessionState mode ="StateServer"
- stateConnectionString ="tcpip=127.0.0.1:42424"
- stateNetworkTimeout ="40">
- </sessionState>
- </system.web>
如上图所示,客户端向服务器发出请求,服务器存储session数据到状态服务器。StateServer可以是当前系统,也可以是不同系统。但它依赖iis.状态服务器的位置在web.config的stateConnectionString属性设置。如果我们设置为127.0.0.1:42424,它将在本地系统中存储数据。可以通过改变ip来改变StateServer的位置,要确保aspnet_state.exe在那个服务器运行,否则在存储数据到session时将得到下面的异常。
当存储数据到session时,数据需要被序列化,使用State Provider把数据存储在StateServer 。获取数据时,State provider返回数据。下图给出这个过程:
例子
步骤 1 : 打开 Visual Studio > 文件 > 新建 > 网站 . 选择位置"http",新建一个web application .如果打开IIS你会看到以web application名称命名的虚拟目录被创建。
步骤2 : 新建一个简单的UI. 我们将存储数据在session中。为此我们新建一个类:"StudentInfo" :
- [Serializable]
- public class StudentInfo
- {
- //Default Constructor
- public StudentInfo()
- {
- }
- /// <summary>
- /// Create object of student Class
- /// </summary>
- /// <param name="intRoll">Int RollNumber</param>
- /// <param name="strName">String Name</param>
- public StudentInfo(int intRoll, string strName)
- {
- this.Roll = intRoll;
- this.Name = strName;
- }
- private int intRoll;
- private string strName;
- public int Roll
- {
- get
- {
- return intRoll;
- }
- set
- {
- intRoll = value;
- }
- }
- public string Name
- {
- get
- {
- return strName;
- }
- set
- {
- strName = value;
- }
- }
- }
- protected void btnSubmit_Click(object sender, EventArgs e)
- {
- StudentInfo _objStudentInfo = new StudentInfo(Int32.Parse( txtRoll.Text) ,txtUserName.Text);
- Session["objStudentInfo"] = _objStudentInfo;
- ResetField();
- }
- protected void btnRestore_Click(object sender, EventArgs e)
- {
- StudentInfo _objStudentInfo = (StudentInfo) Session["objStudentInfo"];
- txtRoll.Text = _objStudentInfo.Roll.ToString();
- txtUserName.Text = _objStudentInfo.Name;
- }
输入数据,提交。
测试现在我们做下面的测试,以打消你的关于StateServer的疑惑。
首先 :删除studentinfo类前面的[ Serializable ]关键字。如果提交会出现下面错误。它说明存在数据前,对象需要被序列化的。接着: 运行应用程序,点击提交按钮,保存数据。重启iis.如果在InProc下,session数据已经丢失。但在StateServer模式下,点击Restore按钮,你仍然可以得到原始session数据。因为State server存储数据不依赖于当前的iis,它独立保存。
最后 : 在Windows Services MMC中,停止aspnet_state.exe, 提交数据. 你将得到下面错误:
因为State Server进程没有运行。
优缺点优点 : * 保存数据独立于iis, 任何iis的问题不会影响Session数据. * 在负载均衡,web农场和web园场景,它很有用. 缺点 : * 处理慢,由于序列化和反序列化。 * State Server需要一直运行。参考更多的信息: * *SQL Server Session 模式
概述
这种sesion模式更安全,更可靠。在这种模式下session数据被序列化存储在SQL Server数据库中。主要缺点还是跟数据的序列化和反序列化的开销有关。这是web农场场景里最好的模式什么时候该用SQL Server Session模式? * 这种模式更安全,更可靠。 * 它集中保存数据于数据库. * 如果发生连续重启服务器,应该使用这种模式。 * 在web园,web农场中,最完美的模式。 * 当在不用的应用程序之间需要共享session数据,可以使用这种模式配置SQL Server Session 模式:在这种模式, 我们存储session数据在SQL Server中, 我们首先需要在web.config提供一个database连接串。可以在web.config中sqlConnectionString 属性提供这个连接串。然后安装,配置SQL Server.我解释怎么使用aspnet_regsql命令配置SQL server。步骤 1: 在命令行,定位到Framework 版本的文件目录例如 :c:\windows\microsoft.net\framework\<version>.步骤 2 : 使用下列参数运行aspnet_regsql命令:参数 | 描述 |
---|---|
-ssadd | 添加SQLServer session 模式支持 |
-sstype p | P代表持久,把session数据持久化到SQL Server |
-S | 指定服务器名 |
-U | 指定用户名 |
-P | 指定密码 |
现在我们只需要改变State Server例子中的web.config连接串。运行应用程序。
存储 Roll 和 User Name, 点击提交按钮。 and 在SQL Server Management Studio,打开ASPStateTempSessions表会看到我们的session数据。测试:
我们做下列测试,同State Server模式一样. 1. 删除StydentInfo类上的Serialize关键字 2. 重启IIS,点击Restore 3. 停止SQL Server服务。 优缺点: 优点 : * 重启IIS,session数据不受影响. * 最可靠,最安全的session模式. * 集中保存数据,易于其它应用程序访问。 * 在web农场,web园模式中很有用。缺点 : * 处理很慢 * 对象的序列化,和反序列化开销大 * 由于session数据被不同的服务器操作,所以要小心对待SQL Server, 它要一直运行参考更多的信息:自定义Session模式
概述:
一般我们都使用InProc, StateServer 或 SQL Server模式,但我们也需要知道自定义session模式基本原理。这种模式很有趣,因为它让我们完全控制每件事甚至session ID.你可以自己写产生session ID的算法。可以通过继承SessionStateStoreProviderBase类实现自定义Provide(保存session数据的机制)。通过实现ISessionIDManager产生新session ID.自定义Session实现期间,下列方法被调用:
在初始化方法中,设置自定义提供者。它将用指定的提供者初始化连接。SetItemExpireCallback用来设置SessionTimeOut,我们能注册任何方法,以在session过期时被调用。InitializeRequest在每次请求时被调用。CreateNewStoreData用来产生一个新的SessionStateStoreData实例。什么时候使用自定义Session模式? * 不想在SQL Server存储session数据. * 想用一些存在的表存储session数据. * 需要产生自己的session ID. 怎么配置? 配置web.config如下:- <system.web>
- <sessionState mode ="Custom" customProvider ="AccessProvider">
- <providers >
- <add name ="AccessProvider" type ="CustomDataType"/>
- </providers>
- </sessionState>
- </system.web>
参考更多的信息:
如果你想知道更多关于session模式的信息,请读这篇Session 和 Cookies 的关系
客户端需要cookies配合session工作。因为客户端需要使用一个适当的session id代表每个请求。
我们可以按照下面操作它:使用cookies:当session被使用时,ASP.NET自动生成一个叫ASP.NET_SessionId的特殊cookies.这是缺省的,Session ID通过这个cookies传递。不使用Cookies:一些老的浏览器不支持Cookies,或者用户在浏览器中禁止Cookies.这是ASP.NET通过特殊标记的URL传输Session ID.无cookies Session怎么工作? 当用户请求一个页面时,服务器编码session ID,把它加到每一页面链接上。当用户点击链接,ASP.NET解码session ID,传送到用户请求的页面。这样在请求页面就可以得到session数据了。如果ASP.NET检测到用户的浏览器不支持Cookies,这一切就自动发生了。怎么实现无cookies Session?- <system.web>
- <sessionState cookieless ="true"></sessionState>
- </system.web>
从Session变量中删除Session
方法 | 描述 |
---|---|
Session.Remove(strSessionName); | 在session集合中删除某项 |
Session.RemoveAll() | 删除session集合中所有项 |
Session.Clear() | 删除session集合中所有项,注意Clear和RemoveAll没有什么不同,内部是RemoveAll()调用Clear() |
Session.Abandon() | 销毁当前的session |
启动或禁用Session
为了性能优化,我们可以启用或禁用session.因为每页读些session都有很大的开销。所以最好的方式是根据需要禁止或启用session。而不是一直启动session.禁止或启用session有两种方式 * 页面级 * 应用程序级 页面级:我们能在Page指令中使用EnableSessionState属性,在页面级禁止session.- <%@ Page Language="C#" EnableSessionState="False"
这将在特定的页面禁止session活动。
同样我们可以设置session只读,这将容许访问数据,不许写session数据。- <%@ Page Language="C#" EnableSessionState="ReadOnly"
- <system.web>
- <!-- Disable Session Applicateion Level -->
- <pages enableSessionState ="false"/>
- </system.web>
通常我们使用页面级别。因为某些页面不需要session,或只读session.
参考更多的信息 :