理解Session的几种模式

(一)概述

我们在使用ASP.NET开发的过程中,有时会进行数据存储以实现请求前后的状态保持(HTTP是无状态保持的协议),而Session作为一种快速简单易于实现的方式被我们经常使用,当然如果出于性能方面的考量,我们还是不建议往Seesion中塞入更多的东西,最好是不用Session。

还有一点需要说明的是,Session实现的本质是在客户端产生一个SessionId,具体的数据存储在服务器端,客户端通过SessionId来获取服务器端的具体数据,那这个SeesionId是怎么保存在客户端以及又是以什么方式来传给服务器的呢?服务器端又是以什么方式保存Session的这些数据的呢?各种方式的优缺点又是什么?这就是本篇随笔想要记录的内容。

(二) 配置方式

<sessionState mode="Off|InProc|StateServer|SQLServer" 
              cookieless="true|false" 
              timeout="number of minutes" 
              stateConnectionString="tcpip=server:port" 
              sqlConnectionString="sql connection string" 
              stateNetworkTimeout="number of seconds" /> 

上面是Session在Web.config的配置方式,下面对各个节点做一些简单的介绍

1.mode(设置将服务器的Session信息存储到哪里)

  • Off表示设置为不使用Session功能;
  • InProc表示将Session存储在进程内,这也是ASP中的存储方式,这是默认值;
  • StateServer表示将Session存储在独立的状态服务即ASP.NET State Service中;
  • SQLServer表示将Session存储在SQL Server。

2.cookieless(设置客户端的Session信息存储到哪里)

  • true表示使用Cookieless模式(这表明SessionId将不再使用Cookie存储了,而是将其通过URL存储);
  • false表示使用Cookie模式,这是默认值。

3.从上面的设置配置中我们也可以发现Session和Cookie的关系:

  • 首先Session在客户端的实现肯定是SessionId;
  • 默认这个SessionId是通过Cookie存储的(比较安全);
  • 当然也可以通过URL来进行存储,这样Session和Cookie就没有关系了,但是此种方式由于受URL长度限制以及明文传送导致不安全而不被推荐使用。

4.timeout

  • Session过期时间设置,默认为20分钟。

5.stateConnectionString

  • 如果设置将Session信息存储在State Server中时,则需要此配置字符串表明服务器名称和端口。

6.sqlConnectionString

  • 如果设置将Session信息存储在SQLServer中,需此配置,表明数据库的连接字符串,同时
    stateNetworkTimeout表明经过多少秒空闲后,断开Web服务器与存储状态信息的服务器的TCP/IP连接的。默认值是10秒钟。

(三)Session服务器端配置

1.InProc

顾名思义,此种模式表示Session将会被保存在内存中,确切地说是保存在工作者进程中,对于IIS 5而言是aspnet_wp.exe,对于IIS 6而言是w3wp.exe,设置方式如下(Web.config)

<sessionState mode="InProc" cookieless="false" timeout="20"/>

由于是直接保存在进程中,所以性能最好,但是经常会发生Session信息丢失,常见的导致进程重启的可能情况为:

  • 配置文件中processModel标签的memoryLimit属性;
  • Global.asax或者Web.config文件被更改;
  • Bin文件夹中的Web程序(DLL)被修改;
  • 杀毒软件扫描了一些.config文件;
  • 系统资源紧张进行资源回收导致IIS进程崩溃或重启等。

2.State Server

此种方式是将Session信息存储在其它的进程中而不是IIS中,这样就可以避免因IIS进程崩溃或重启而导致的Session信息丢失。但是此种方式要求保存在Session的信息必须序列化,然后从Session中获取的时候也要反序列化,这就导致性能有略微的损失。

<sessionState mode="StateServer" cookieless="false" timeout="20"/>

StateServer是本机的一个服务,可以在系统服务里看到服务名为ASP.NET State Service的服务,默认情况是不启动的。当我们设定mode为StateServer之后,请把该服务的启动模式设置为自动(这样下次服务就可以随机器而启动)并手工将该服务启动运行。这样,我们就能利用本机的StateService来存储Session了,除非电脑重启或者StateService崩掉,否则Session是不会丢的。

<sessionState mode="StateServer" stateConnectionString="tcpip=127.0.0.1:42424" cookieless="false" timeout="20"/>

此种配置和上面是一样的(多了个stateConnectionString,换句话说127.0.0.1是默认本机IP,42424默认是该服务的访问端口号,写不写效果是一样的),都表示StateServer是在本机(注:StateServer模式是支持远程主机服务的,配置类似与下面)

<sessionState mode="StateServer" stateConnectionString="tcpip=10.7.10.87:42424" cookieless="false" timeout="20"/>

3. SQL Server

此种方式是把Session信息保存在SQL Server的数据库中,也需要序列化,性能有较大损失,但是Session一般不会发生丢失的情况,除非SQL Server宕机。而且此种方式也可以实现在Web Farm中的Session信息共享(上面两种方式都不可以)。

<sessionState mode="SQLServer" sqlConnectionString ="data source=10.7.11.114; user id=session_user; password=Session@Pwd" timeout="20" />

(四)Session客户端配置

再次说明,Session的实现分为两个部分:客户端和服务器端,其中客户端负责产生SessionId,服务器端负责保存具体的内容,这儿所说的Session客户端配置其实是想说说关于SessionId的一些东西。

1. Session在客户端是如何实现的?

  • 前面已经说过,Session在客户端是通过产生SessionId来实现的,至于这个SessionId又是通过什么方式回传之服务器从而获得具体的Session内容,前面也略有说明,两种方式:Cookie和Url,由于Url的方式会导致安全性问题,所以现在一般已不再使用此种方式。

  • 当系统是用Session的时候,系统将自动在客户端产生一个Cookie,名称为ASP.NET_SessionId,为了便于区别,我们暂且将此Cookie称为Session
    Cookie

2. Session Cookie何时失效?

  • 和一般的Cookie一样,默认是保存在浏览器的内存中,当浏览器关闭时失效,如果想此Cookie保存在本地磁盘,可通过设置其Expires属性来达到,这种方式现在也被广泛应用于网站的登录,即用户在登录的时候选择记住我或保持登录一段时间,这样当用户下次再次访问的时候就无需再次输入用户名密码从而达到快速访问的目的
HttpCookie httpCookie = new HttpCookie("ASP.NET_SessionId", Request.Cookies["ASP.NET_SessionId"].Value);
httpCookie.Expires = DateTime.Now.AddMinutes(20);
Response.Cookies.Add(httpCookie);
if (!string.IsNullOrEmpty(Request.Cookies["ASP.NET_SessionId"].Value))
{
    //...处理相关登录验证等信息
    Response.Redirect("Default.aspx?UserName=" + loginUser.UserName + "");
}

3. Session Cookie失效时Session失效吗?

  • 答案当然是否定的,记住:Session Cookie和Session的失效没有任何必然的联系,因为它们失效的基准或者条件根本不一样,Session Cookie的失效时间取决于客服端Cookie的失效时间,如果是保存在浏览器中,那么关闭浏览器Session Cookie就将失效,否则如果保存在本地磁盘,则取决于该Session Cookie设置的过期时间;而服务器端的Session是保存在服务器端的,它的失效与否与其服务器端的设置和Session的过期时间有关(下面的讨论将忽略过期时间这个因数,你懂的),如果是InProc方式,那么当承载的IIS进程如果奔溃或重启等都会丢失;如果是State Server,同样如果这个Service宕掉,那Session也会丢失;而如果是SQL Server,则会写入数据库,如果你不删除它,它甚至可以一直存在而永不丢失(事实是SQL Server Agent会自动运行一个Job删除过期的Session);而当如果我们使用自定义的数据库来保存Session时,你将获得充分的控制。

4.Session Cookie何时产生?刷新页面其值会改变吗?

  • 牢记一点,只有当使用Session的时候才会产生Session Cookie。你也许会反问那为什么当配置Session模式为SQLServer时,就算没有使用Session,也可以获得ASP.NET_SessionId的值,即在Page_Load的时候执行方法Response.Write(Request.Cookies[“ASP.NET_SessionId”].Value),会输出值,我的猜测是虽然你可以获得ASP.NET_SessionId值,但实际上并没有真正产生Session Cookie,因为此时当我试图通过HttpWatch(下面介绍的工具)来查看此Session Cookie的时候根本查不到,当然这也只是我的个人猜测而已,至于具体的内部机制还是不甚了解。

当没有使用Session的时候刷新页面Session Cookie的值会变化吗?答案是会的,测试方法如上,设置Session模式为SQLServer,在Page_Load的时候输出Session Cookie的值,然后一直F5页面即可,你会看到其值一直在变化,直到在代码中明确地使用Session后便不再变化。

public partial class Login : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        Response.Write(Request.Cookies["ASP.NET_SessionId"].Value);
    }

    protected void tbnLogin_Click(object sender, EventArgs e)
    {
        if (!string.IsNullOrEmpty(this.txtUserName.ToString()) && !string.IsNullOrEmpty(this.txtPassword.ToString()))
        {
            LoginUser loginUser = new LoginUser();
            loginUser.UserId = Guid.NewGuid().ToString("N");
            loginUser.UserName = this.txtUserName.Text;
            loginUser.UserPassword = this.txtPassword.Text;
            Session["LoginUser"] = loginUser;
        }
    }
}

(五)Session的其它相关问题

1. 如何捕获Global.asax中的Session_End()事件?

  • Session的服务器端模式必须配置为InProc,其它两种模式(State Server或SQL
    Server)无法获得Session_End事件;
  • Session过期时,此事件才会发生,与用户是否关闭浏览器无关(关闭浏览器唯一可能的影响是此Session在客户端部分产生的Cookie失效,而服务器端Session继续存在,而且此时Cookie失效的前提也是把Cookie保存在浏览器中)

2. 如果提高客户端Session Cookie的安全性?

  • 指定HttpCookie对象的HttpOnly属性为true,此属性用于标识一个Cookie是否可通过客户端脚本访问,true为可以,false为不可以,默认为false。设定的方式有两种:编程或配置文件。注意此属性并不能完全阻止客户端在本地获取cookies(上面已经介绍过如果获取此session
    cookie),但是可以增加通过脚本直接获取的难度。另外,Microsoft Internet Explorer 版本 6 Service
    Pack 1 和更高版本支持 Cookie 属性 HttpOnly。
HttpCookie sessionCookie = new HttpCookie("ASP.NET_SessionId");
sessionCookie.HttpOnly = true;
<httpCookies httpOnlyCookies="true" />
  • 对Cookies实行加密和用https传输:
HttpCookie sessionCookie = new HttpCookie("ASP.NET_SessionId");
sessionCookie.HttpOnly = true;
sessionCookie.Secure = true;
<httpCookies httpOnlyCookies="true" requireSSL="true" />
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值