1、ASP.NET 會話狀態(tài)
2、會話狀態(tài)模式
3、ASP.NET在不同應(yīng)用程序之間共享Session
4、Session無故丟失
5、客戶端使用Cookieless的方式存儲Session信息
6、Session.SessionID 固定
1、ASP.NET 會話狀態(tài)
會話狀態(tài)可在以下情況下使用:存儲特定于單獨會話的短期信息,并且需要較高的安全性。不要在會話狀態(tài)中存儲大量的信息。需要注意,將為應(yīng)用程序中每一會話的生存期創(chuàng)建并維護會話狀態(tài)對象。在支持許多用戶的應(yīng)用程序中,這可能會占用大量服務(wù)器資源并影響可縮放性。*p1
ASP.NET 默認情況下將會話信息存儲在 ASP.NET 應(yīng)用程序的內(nèi)存空間。您可以使用一個獨立的服務(wù)存儲會話信息以便重新啟動 ASP.NET 應(yīng)用程序后會話信息仍然保留;或?qū)捫畔⒋鎯υ?SQL Server 中以便會話信息可供網(wǎng)絡(luò)場中的多個 Web 服務(wù)器使用(重新啟動 ASP.NET 應(yīng)用程序后會話信息也會保留);或?qū)捫畔⒋鎯υ谧远x數(shù)據(jù)存儲區(qū)。有關(guān)更多信息,請參見會話狀態(tài)模式。
除了會話狀態(tài)外,ASP.NET 還提供在應(yīng)用程序中保留數(shù)據(jù)的一些其他方式。有關(guān)每種方式的比較,請參見 ASP.NET 狀態(tài)管理建議。*p2
注:
*p1:ASP.NET 狀態(tài)管理建議 http://msdn.microsoft.com/zh-cn/library/z1hkazw7(v=VS.80).aspx
*p2:ASP.NET 會話狀態(tài) http://msdn.microsoft.com/zh-cn/library/87069683(v=VS.80).aspx
2、會話狀態(tài)模式
ASP.NET 會話狀態(tài)支持若干用于會話數(shù)據(jù)的存儲選項。每個選項都由 SessionStateMode 枚舉中的一個值標識。下面的列表描述了可用的會話狀態(tài)模式:
- InProc 模式,此模式將會話狀態(tài)存儲在 Web 服務(wù)器上的內(nèi)存中。這是默認設(shè)置。注意:它是唯一支持 Session_OnEnd 事件的模式。
- StateServer 模式,此模式將會話狀態(tài)存儲在一個名為 ASP.NET 狀態(tài)服務(wù)的單獨進程中。這確保了在重新啟動 Web 應(yīng)用程序時會保留會話狀態(tài),并讓會話狀態(tài)可用于網(wǎng)絡(luò)場中的多個 Web 服務(wù)器。注意:如果模式設(shè)置為 StateServer,則存儲在會話狀態(tài)中的對象必須是可序列化的。
- SQLServer 模式,將會話狀態(tài)存儲到一個 SQL Server 數(shù)據(jù)庫中。這確保了在重新啟動 Web 應(yīng)用程序時會保留會話狀態(tài),并讓會話狀態(tài)可用于網(wǎng)絡(luò)場中的多個 Web 服務(wù)器。注意:如果是 SQL Server 模式,則存儲在會話狀態(tài)中的對象必須是可序列化的。
- Custom 模式,此模式允許您指定自定義存儲提供程序。
- Off 模式,此模式禁用會話狀態(tài)。
通過在應(yīng)用程序的 Web.config 文件中為 sessionState 元素的 mode 屬性分配一個 SessionStateMode 枚舉值,可以指定要讓 ASP.NET 會話狀態(tài)使用的模式。除了 InProc 和 Off 之外,其他模式都需要附加參數(shù),例如將在本主題后面討論的連接字符串值。通過訪問 System.Web.SessionState.HttpSessionState.Mode 屬性的值,可以查看當前選定的會話狀態(tài)。*p3
注:
*p3:會話狀態(tài)模式 http://msdn.microsoft.com/zh-cn/library/ms178586(v=VS.80).aspx
3、ASP.NET在不同應(yīng)用程序之間共享Session *p4
多個單獨的應(yīng)用程序,如何將這些模塊集中身份驗證與授權(quán)過程
方案1:
將每個獨立的Web應(yīng)用程序放到統(tǒng)一的解決方案中,實現(xiàn)起來復雜,易用性不高。
方案2:利用Session會話共享
InProc模式,Session被存儲在IIS進程中,每個虛擬目錄是隔離的,所以無法共享Session。
StateServer 模式,雖然是獨立的狀態(tài)服務(wù)器(進程),但在內(nèi)存中這些應(yīng)用程序還是隔離的。
SQLServer 模式,由于對Session的全部操作都是由存儲過程來實現(xiàn)的,而且存儲過程未進行加密,可以通過修改存儲過程的內(nèi)部結(jié)構(gòu)來達到共享的目的。
ASPState數(shù)據(jù)庫ASPStateTempApplications表中存儲的是應(yīng)用程序信息,每個應(yīng)用程序在啟動的時候在這里會注冊一條記錄,包括應(yīng)用程序的ID(通過哈希算法生成的)和應(yīng)用程序名稱。有多少個應(yīng)用程序,在這個表里就對應(yīng)多少條記錄。那我們現(xiàn)在要做的是把這些記錄變成一條記錄,也就是要欺騙Framework,讓它認為這些不同的應(yīng)用程序是同一個應(yīng)用程序。
TempGetAppID存儲過程,這個存儲過程是用于通過傳遞應(yīng)用程序名稱來得到應(yīng)用程序ID信息的。每個應(yīng)用程序在調(diào)用這個過程時,這個過程會去AspStateTempApplications中檢查是否有相應(yīng)的記錄,如果沒有,就插入記錄,然后返回相應(yīng)的ID。
ALTER PROCEDURE [dbo].[TempGetAppID]
@appName tAppName,
@appId int OUTPUT
AS
SET @appName = LOWER(@appName)
--變量值固定,使所有應(yīng)用程序通用為一個
SET @appName = '/lm/w3svc/650056020/root/personnel/share'
SET @appId = NULL
SELECT @appId = AppId
FROM [tempdb].dbo.ASPStateTempApplications
WHERE AppName = @appName
注:
*p4:ASP.NET在不同應(yīng)用程序之間共享Session http://www.3qsoft.com/Article.aspx?ID=173
4、Session無故丟失 *p5
mode="InProc"
==
默認的配置方式很容易丟失Session 請參考
asp中Session的工作原理:
asp的Session是具有進程依賴性的。ASP Session狀態(tài)存于IIS的進程中,也就是inetinfo.exe這個程序。所以當inetinfo.exe進程崩潰時,這些信息也就丟失。另外,重起或者關(guān)閉IIS服務(wù)都會造成信息的丟失。
原因1:
bin目錄中的文件被改寫,asp.net有一種機制,為了保證dll重新編譯之后,系統(tǒng)正常運行,它會重新啟動一次網(wǎng)站進程,這時就會導致Session丟失,所以如果有access數(shù)據(jù)庫位于bin目錄,或者有其他文件被系統(tǒng)改寫,就會導致Session丟失
原因2:
文件夾選項中,如果沒有打開“在單獨的進程中打開文件夾窗口”,一旦新建一個窗口,系統(tǒng)可能認為是新的Session會話,而無法訪問原來的Session,所以需要打開該選項,否則會導致Session丟失
原因3:
似乎大部分的Session丟失是客戶端引起的,所以要從客戶端下手,看看cookie有沒有打開
原因4:
Session的時間設(shè)置是不是有問題,會不會因為超時造成丟失
原因5:
IE中的cookie數(shù)量限制(每個域20個cookie)可能導致session丟失
原因6:
使用web garden模式,且使用了InProc mode作為保存session的方式
解決丟失的經(jīng)驗
1. 判斷是不是原因1造成的,可以在每次刷新頁面的時候,跟蹤bin中某個文件的修改時間
2. 做Session讀寫日志,每次讀寫Session都要記錄下來,并且要記錄SessionID、Session值、所在頁面、當前函數(shù)、函數(shù)中的第幾次Session操作,這樣找丟失的原因會方便很多
3. 如果允許的話,建議使用state server或sql server保存session,這樣不容易丟失
4. 在global.asa中加入代碼記錄Session的創(chuàng)建時間和結(jié)束時間,超時造成的Session丟失是可以在SessionEnd中記錄下來的。
5. 如果有些代碼中使用客戶端腳本,如javascript維護Session狀態(tài),就要嘗試調(diào)試腳本,是不是因為腳本錯誤引起Session丟失
問:為什么Session在有些機器上偶爾會丟失?
答:可能和機器的環(huán)境有關(guān)系,比如:防火墻或者殺毒軟件等,嘗試關(guān)閉防火墻。
問:為什么當調(diào)用Session.Abandon時并沒有激發(fā)Session_End方法?
答:首先Session_End方法只支持InProc(進程內(nèi)的)類型的Session。其次要激發(fā)Session_End方法,必須存在Session(即系統(tǒng)中已經(jīng)使用Session了),并且至少要完成一次請求(在這次請求中會調(diào)用該方法)。
問:為什么當我在InProc模式下使用Session會經(jīng)常丟失?
答:該問題通常是由于應(yīng)用程序被回收導致的,因為當使用進程內(nèi)Session時,Session是保存在aspnet_wp進程中,當該進程被回收Session自然也就沒有了,確定該進程是否被回收可以通過查看系統(tǒng)的事件查看器獲得信息。
具體信息請參考:
Session variables are lost intermittently in ASP.NET applications
http://support.microsoft.com/default.aspx?scid=kb;en-us;Q316148
在1.0的時候也有一個bug會導致工作進程被回收并重啟,該bug已經(jīng)在1.1和sp2中修復。
關(guān)于該bug的詳細信息請參考:
ASP.NET Worker Process (Aspnet_wp.exe) Is Recycled Unexpectedly.
http://support.microsoft.com/default.aspx?scid=kb;en-us;Q321792
問:什么類型的對象可以保存在Session里?
答:這依賴使用的Session的模式,當使用的是進程內(nèi)(InProc)的Session那么可以輕松的保存任何對象。如果你使用了非InProc的模式,則只能保存可以序列化和反序列化的對象,如果此時保存的對象不支持序列化,則不能保存到這種模式(非InProc)的Session里。
問:為什么在Session_End中不能使用Response.Redirect和Server.Transfer方法跳轉(zhuǎn)頁面?
答:Session_End是一個在服務(wù)器內(nèi)部激發(fā)的事件處理函數(shù)。它是基于一個服務(wù)器內(nèi)部的計時器的,在激發(fā)該事件時服務(wù)器上并沒有相關(guān)的HttpRequest對象,因此此時并不能使用Response.Redirect和Server.Transfer方法。
問:在Session_End中是否可以獲得HttpContext對象?
答:不行,因為這個事件并沒有和任何的請求(Request)相關(guān)聯(lián),沒有基于請求的上下文。
問:在Web Service中該如何使用Session?
答:為了在Web Service中使用Session,需要在Web Service的調(diào)用方做一些額外的工作,必須保存和存儲調(diào)用Web Service時使用的Cookie。詳細信息請參考MSDN文檔的HttpWebClientProtocol.CookieContainer屬性。然而,如果你使用代理服務(wù)器訪問Web Service由于框架的限制,兩者不能共享Session。
問:當我使用webfarm時,當我重定向到其他的Web服務(wù)器時Session為什么會丟失?
答:詳細信息請參考:
PRB: Session State Is Lost in Web Farm If You Use SqlServer or StateServer Session Mode
http://support.microsoft.com/default.aspx?scid=kb;en-us;325056
問:Session在global.asax中的那些事件中有效?
答:Session只有在AcquireRequestState事件之后有效,該事件之后的事件都可以使用Session。
問:為了可以順序訪問Session的狀態(tài)值,Session是否提供了鎖定機制?
答:Session實現(xiàn)了Reader/Writer的鎖機制:
當頁面對Session具有可寫功能(即頁面有 <%@ Page EnableSessionState="True" %>標記),此時直到請求完成該頁面的Session持有一個寫鎖定。
當頁面對Session具有只讀功能(即頁面有 <%@ Page EnableSessionState="ReadOnly" %>標記),此時知道請求完成該頁面的Session持有一個讀鎖定。
讀鎖定將阻塞一個寫鎖定;讀鎖定不會阻塞讀鎖定;寫鎖定將阻塞所有的讀寫鎖定。這就是為什么兩個框架中的同一個頁面都去寫同一個Session時,其中一個要等待另一個(稍快的那個)完成后,才開始寫。
問:Session平滑超時意味著什么?
答:Session平滑超時意味著只要你的頁面訪問(使用)了Session,超時時間將被刷新(可以理解為重新計時),即從該頁面請求開始,將重新計算超時時間。但是,該頁面不能禁用Session。它會自動的訪問當前頁面的Session,刷新超時時間。
問:在global.asax中的事件處理函數(shù)中Session為什么無效?
答:依賴于在哪個事件處理函數(shù)中使用Session,Session在AcquireRequestState事件之后才有效,該事件之后的所有事件處理函數(shù)都可以使用Session,之前的則不能。
問:當我使用InProc模式保存Session時,此時的Session是保存在哪里?
答:不同的IIS的處理方式不同,
當使用的是IIS5的時候Session是保存在aspnet_wp.exe的進程空間里的。
當使用的是IIS6時,默認情況下所有的應(yīng)用程序共享應(yīng)用程序池,Session保存在w3wp.exe的進程空間中。
問:當頁面出現(xiàn)錯誤后我的Session是否將被保存?我需要在Session_End中處理一些清理工作,但是失敗了,為什么?
答:Session_End只有在Session運行在InProc模式下才會被執(zhí)行。Session_End使用的帳號是運行aspnet_wp工作進程的帳號(這個可以在machine.config中設(shè)置)。因此,如果在Session_End方法里,使用集成安全性鏈接到SQL,它將使用aspnet_wp進程的帳號打開鏈接,此時成功與否則依賴于你的SQL的安全性設(shè)置。
問:在Session_End是我是否可以獲得有效的HttpSessionState和HttpContext對象?
答:你可以在這個方法中獲得HttpSessionState對象,可以直接使用Session來訪問即可。但是不能獲得HttpContext對象,因為該事件并沒有和任何請求相關(guān)聯(lián),因此不存在上下文對象。
問:在SQLServer模式下使用Session,為什么我的Session不過期?
答:在SqlServer模式下,Session的過期是通過SQL Agent的注冊工作完成的,請檢查你的SQL Agent是否運行?
問:當我設(shè)置EnableSessionState為“ReadOnly”后,但是我在InProc模式下依然可以修改Session的值,這是為什么?
答:即使EnableSessionState標示為ReadOnly,但是在InProc模式下用戶依然可以編輯Session。唯一不同的是,在請求過程中Session將不會被鎖住。
問:為什么在切換成SQLServer模式后我的請求被掛起了?
答:檢查在Session里面是否都保存的是可以保存在SQLServer模式下的對象,即這些對象必須支持序列化。
問:當Session設(shè)置成cookieless后會有什么影響?
答:當把cookieless設(shè)置成true時,主要會有下面的約束:
1、在頁面中不能使用絕對鏈接
2、在應(yīng)用程序中在除了Http和Https之間的切換時需要完成一些其他的步驟。
如果發(fā)送一個鏈接給其他人,此時的URL里面將包含Session ID的信息,所以兩個人將公用一個Session。
注:
*p5:Session丟失 http://topic.csdn.net/u/20081208/14/c154543c-8e86-406b-82a2-d3cc6f736b0d.html
5、客戶端使用Cookieless的方式存儲Session信息
sessionState中的cookieless="false"改為:cookieless="true",這樣,客戶端的Session信息就不再使用Cookie存儲了,而是將其通過URL存儲。關(guān)閉當前的IE,打開一個新IE,重新訪問剛才的Web應(yīng)用程序,瀏覽器地址就會變?yōu)?http://localhost/MyTestApplication/(
ulqsek45heu3ic2a5zgdl245)/default.aspx中黑體標出的就是客戶端的Session ID。注意,這段信息是由IIS自動加上的,不會影響以前正常的連接。 *p6
問:當Session設(shè)置成cookieless后會有什么影響?
答:當把cookieless設(shè)置成true時,主要會有下面的約束:
1、在頁面中不能使用絕對鏈接
2、在應(yīng)用程序中在除了Http和Https之間的切換時需要完成一些其他的步驟。
如果發(fā)送一個鏈接給其他人,此時的URL里面將包含Session ID的信息,所以兩個人將公用一個Session。 *p7
注:
*p6:[ASP.NET] Session 詳解
http://www.blueidea.com/tech/program/2004/1856.asp
*p7:Session丟失
http://topic.csdn.net/u/20081208/14/c154543c-8e86-406b-82a2-d3cc6f736b0d.html
6、Session.SessionID 固定
- IsNewSession:取得值,指出工作階段是否以目前要求建立。
- SessionID:取得工作階段的唯一工作階段識別項。
re: 因為Session在還沒裝物件之前, ID都不是固定的. 如果您賦予Session內(nèi)容, ex: Session["xxx"]=123 , 您會發(fā)現(xiàn)ID就會固定. *p8
注:
*p8:[ASP.Net]Session.IsNewSession與Session.SessionID http://www.dotblogs.com.tw/yilinliu/archive/2009/04/24/8163.aspx
posted on 2010-05-10 10:34
黃小二 閱讀(637)
評論(0) 編輯 收藏 所屬分類:
ASP.NET