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"/
相關文章
相關標籤/搜索