天天看點

艾偉_轉載:ASP.NET Session詳解

當使用者在 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 中。

ASP.NET 通過自動在頁的 URL 中插入唯一的會話 ID 來保持無 Cookie 會話狀态。例如,下面的 URL 已被 ASP.NET 修改,以包含唯一的會話 ID lit3py55t21z5v55vlm25s55:

<a href="http://www.example.com/(S(lit3py55t21z5v55vlm25s55))/orderform.aspx">http://www.example.com/(S(lit3py55t21z5v55vlm25s55))/orderform.aspx</a>

搭建Session伺服器的幾種方式

将Session儲存在獨立的伺服器中可以實作在多台Web伺服器之間共享Session.雖然我們也可以自己開發Session存儲系統, 但是使用ASP.NET自帶的存儲機制将更加便捷.

.NET提供了5種儲存Seission的方式:

方式名稱

存儲方式

性能

Off

設定為不使用Session功能

InProc

設定為将Session存儲在程序内,就是ASP中的存儲方式,這是預設值。

性能最高

StateServer

設定為将Session存儲在獨立的狀态服務中。通常是aspnet_state.exe程序.

性能損失10-15%

SQLServer

性能損失10-20%

Customer

自定制的存儲方案

由實作方式确定

我們可以在Web.Config中配置程式使用的Session存儲方式.預設情況下是InProc, 即儲存在IIS程序中. 關于Off, InProc和Customer本文不做講解. 相關文章大家都可以在網上搜尋到.

下面主要講解 StateServer 和 SQLServer 的應用.

四.使用 StateServer 模式搭建Session伺服器

(1)伺服器端配置

1.啟動 Asp.net State service服務.(這個服務預設的狀态為手動.修改為自動并啟動.)

2.修改系統資料庫: [HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\aspnet_state\Parameters]

設定 AllowRemoteConnection = 1 , 設定 Port = 42424 (十進制,預設即為42424)

Port是服務的端口号

AllowRemoteConnection 表示是否允許其他機器連接配接,0為僅能本機使用,1為可以供其他機器使用.

(2)用戶端設定

在Web應用程式的Web.Config中, 我們需要修改 / 的節點.如果沒有

沒有則添加(預設使用的是InProc方式)

上面的參數我們可以根據需要修改.

五.使用SqlServer模式搭建Session伺服器

使用SqlServer模式搭建Session伺服器端有兩種方式. ASP.NET 1.0和1.1版本請使用方式a, 2.0即以上版本請使用方式b.

在ASP.NET 1.0和1.1 版本中, 隻能使用這種方式.對于2.0及其以上版本,請使用aspnet_regsql.exe工具.(當然此方法也通用2.0版本)

根據ASP.NET的版本不同, 需要使用不同的SQL腳本. ASP.NET主要有1.1和2.0兩個版本,可以在不同的版本檔案夾找到這兩個SQL.

b. 使用aspnet_regsql.exe工具

使用舉例:

aspnet_regsql.exe -S . -U sa -P 123456 -ssadd -sstype p

-S參數:

-U和-P參數:

表示使用者名和密碼.

-E參數:

-ssadd / –ssremove 參數:

sstype 參數:

選項

說明

t

p

c

(2)Session用戶端設定

六.使用經驗與技巧總結

下面是SessionID, Session_End時間, StatServer模式 和 SqlServer模式的各種經驗和技巧總結.

(1)StateServer模式:

1.在web farm中,請确認在所有的web伺服器上有相同的

2. 要儲存在Session中的對象是可序列化的。

3.為了在web farm中的不同web伺服器上維護session state,IIS Metabase中的網站應用程式路徑(如\LM\W3SVC\2)應該在所有的伺服器上保持一緻(大小寫敏感).

4. ASP.NET處理Session是在Machine.Config中配置的HttpModuel子產品, 在.NET的安裝目錄下的Config檔案夾中, 檢視Web.Config(1.1版本是在Machine.Config):

确認此子產品是否存在.

5.StateServer不支援負載均衡, 是以如果大并發推薦使用SqlServer模式, 可以享受到SqlServer的高性能和安全性.雖然存儲效率會有下降.

6.需要讓所有機器的MachineKey相同.在Machine.Config中配置:

(2)SqlServer模式:

1. 要儲存在Session中的對象是可序列化的。

5.需要讓所有機器的MachineKey相同.在Machine.Config中配置:

(3)Session:

http://msdn.microsoft.com/zh-cn/library/aa479313.aspx

2. 在不同的應用程式或一個網站的不同虛拟目錄之間無法共享Session

3. Session的過期時間是滑動時間.

4. Session存儲.NET自帶的值類型性能最優. 存儲對象會降低性能.

(4)SessionID:

1.SessionID 還可以儲存在URL上, 設定Web.Config檔案中的System.Web/sessionState節點的Cookiesless屬性即可:

2. 一般在Session逾時或删除之後,SessionID保持不變. 因為Session過期後會在伺服器端清除資料, 但是SessionID儲存在使用者浏覽器上, 是以隻要浏覽器不關閉則HTTP頭中的SessionID保持不變.

3.關閉浏覽器後再通路, SessionID會不同.

4.每打開一個IE6視窗, SessionID都不同, 在IE6中兩個視窗的Session不能共享.

5.FireFox的标簽頁和新的FireFox視窗, SessionID都相同, 在FF的視窗和标簽頁上Session能共享.

6.對于包含FrameSet的頁面,比如:

如果字尾名是.htm并且.htm檔案沒有交給ASP.NET的ISAPI處理, 那麼根據伺服器速度在每個Frame頁面生成不同的SessionID, 再重新整理後相同都等于最後一個SessionID.

 解決辦法是将.htm字尾改成.aspx, 或者将.htm檔案交給ASP.NET的ISAPI處理.

(5)Session_End事件:

1. Session_End僅在InProc模式中可用

2. 關閉浏覽器,Session_End是不會觸發的。HTTP是一種無狀态協定,伺服器沒有辦法知道你的浏覽器是否已經關閉。

3. 當Session因為時間過期或調用Session.Abandon時,Session_End才會觸發.Session.Clear()僅僅是清除資料,但沒有删除session。

4. Session_End由一個背景線程觸發,使用工作者程序賬号運作. 是以程式不會通知發生的錯誤.

6.因為Session_End是有獨立線程出發的, 是以在Session_End中無法使用HttpContext對象(Request,Response,Server等對象都在HttpContext中), 即無法使用 Response.Redirect 和Server.Transfer等方法.

七.總結

我已經使用SqlServer模式對公司的多台伺服器實作了Session共享, 伺服器重新開機也不會導緻使用者預定過程重新開始(預定過程需要的Session不會丢失). 希望本文對具體的Session伺服器搭建人員有所幫助.