Asp.NET 的Session实现原理 转自21kaiyun.com

Session每天用,可是你真的理解了么?
今天遇到了这个问题,因而研究了一下。要解决这个问题,首先就要明白一些Session的机理。Session在服务器是以散列表形式存在的,咱们都知道Session是会话级的,每一个用户访问都会生成一个Session。那么服务器是怎么区分不一样用户的Session?又是怎么将不一样用户的Session与不一样的用户绑定的呢?下面咱们来研究一下,如下纯属我我的的理解,若有错误请指证。
Session在服务器端是以散列表的形式存在的,区分每个Session是经过SessionID来实现的,因此能够说这个SessionID是一个Key是一个全局惟一的值。咱们能够经过ASP.NET来打印出SessionID,以下代码:

protectedvoidPage_Load(objectsender,EventArgse)
{
Response.Write(Session.SessionID.ToString());
}


这样咱们就获得了这样的值:0julmoedn0kz3gyfnr1vksv0,有点像是GUID,就算不是算法也都是相似的,主要就是为了保证全局惟一性。这样就达到了区分不一样用户的Session的目的。接下来还有第二个问题,那就是SessionID有了,可是它又是怎么和相应的访问者(用户)绑定的呢?好比说用户A访问维护了本身的SessionID,用户B访问也维护了本身的SessionID。咱们都知道web是基于http无连接的,他们又是怎么作到的呢?没错,答案就是在客户端存储了本身的SessionID。浏览器存储SessionID有两种方式,一种就是利用Cookies;还有一种就是利用url参数(这种咱们不经常使用,很不友好)。
话题说到Cookies上来了,怎么的?没想到Session和Cookies还有这样的关系吧?(不少人知道,别BS我)没错,当咱们请求一个URL时候,服务器会生成一个全局的SessionID,而且把这个值以Cookies的形式保存在客户端也就是浏览器(这里暂不讨论url方式)。这样当用户再去请求的时候,在http头把这个SessionID的Cookie发到服务器端,服务器就去找这个SessionID,若是找到了。就证实这个用户的状态是存在的。
知道了这个原理,咱们的问题也就有眉头了,即然是用Cookies来保存SessionID,那么咱们就能够在Cooikes上作手脚了。咱们都知道Cooikes记录方式是以域(例如21世纪开运网:http://www.21kaiyun.com/)为区分的,这也是各类浏览器规定的。若是不这么作,安全性就会有问题。咱们要作的就是让指定Cookies的父域方式,不指定具体指域,这样Cookies就能够跨子域了。Cookies能够像这样指定域:

protectedvoidPage_Load(objectsender,EventArgse)
{
Response.Cookies["MyCook"].Domain=".local.com";
}


这样,咱们全部的二级域所有是认这一个主域的,好比a.local.com;b.local.com;user.local.com等等。有了这个认识,我想你们内心也有数了,该怎么怎么作,可是如今问题是用来生成SessionID的方法是ASP.NET自动实现的,咱们又怎么去干涉它呢?这是这样作的,不主动干涉它,可是我能够操做它的Cookies啊。接下来咱们就研究ASP.NET存SessionID的Cooike的名字是什么。通过网上很容易就查找到了,名字是:ASP.NET_SessionId,这个就是SessionId的Cookies名字。咱们能够在Session_Start中这样写:


代码 protectedvoidSession_Start(objectsender,EventArgse) { Response.Cookies["ASP.NET_SessionId"].Value=Session.SessionID.ToString(); Response.Cookies["ASP.NET_SessionId"].Domain=".local.com"; } 代码的意思是每次会话开始的时候,我都把ASP.NET_SessionId这个Cookie重写成咱们已有的SessionID,而且把这个Cookie的domain指定为父域,好比:.local.com,这样就能够实现跨子域的Session共享了。怎么样很简单吧? 咱们还有一个外题问题,就是客户端保存的问题解决了,可是服务器端的Session怎么办?通常状况下咱们不一样的子域作的是指向不一样的服务器的,好比user.local.com 专门一台服务器,yellow.local.com专门一台服务器。这时它们别说是进程了,连物理上都不是一个了。Session怎么共享?这时就用到另外一个方法了,咱们默认的Session是存储在asp.net进程中的,这样无法互相访问,以下面所示: sessionStatemode="InProc"/ 咱们能够修改成State Server方式,这是一个单独的服务能够用来存储ASP.NET Session的,它支持分布式远程主机的,这样咱们能够用一台服务器来提供Session服务,以下所示: sessionStatemode="StateServer"stateConnectionString="tcpip=127.0.0.1:42424"timeout="30"/ 这样,就彻底实现了不一样子域的Session共享了。 前面说到Url保存SessionId的方式,因为不经常使用,给你们演示一下,以下配置就能够了: sessionStatemode="StateServer"stateConnectionString="tcpip=127.0.0.1:42424"timeout="30"cookieless="true"/
相关文章
相关标签/搜索