1、ASP.NET 工作階段狀態
2、工作階段狀態模式
3、ASP.NET在不同應用程式之間共用Session
4、Session無故丟失
5、用戶端使用Cookieless的方式儲存Session資訊
6、Session.SessionID 固定
1、ASP.NET 工作階段狀態
工作階段狀態可在以下情況下使用:儲存特定於單獨會話的短期資訊,並且需要較高的安全性。不要在工作階段狀態中儲存大量的資訊。需要注意,將為應用程式中每一會話的生存期建立並維護工作階段狀態對象。在支援許多使用者的應用程式中,這可能會佔用大量伺服器資源並影響可縮放性。*p1
ASP.NET 預設情況下將會話資訊儲存在 ASP.NET 應用程式的記憶體空間。您可以使用一個獨立的服務儲存會話資訊以便重新啟動 ASP.NET 應用程式後會話資訊仍然保留;或將會話資訊儲存在 SQL Server 中以便會話資訊可供網路場中的多個 Web 服務器使用(重新啟動 ASP.NET 應用程式後會話資訊也會保留);或將會話資訊儲存在自訂資料存放區區。有關更多資訊,請參見工作階段狀態模式。
除了工作階段狀態外,ASP.NET 還提供在應用程式中保留資料的一些其他方式。有關每種方式的比較,請參見 ASP.NET 狀態管理建議。*p2
注:
*p1:ASP.NET 狀態管理建議 http://msdn.microsoft.com/zh-cn/library/z1hkazw7(v=VS.80).aspx
*p2:ASP.NET 工作階段狀態 http://msdn.microsoft.com/zh-cn/library/87069683(v=VS.80).aspx
2、工作階段狀態模式
ASP.NET 工作階段狀態支援若干用於會話資料的儲存選項。每個選項都由 SessionStateMode 枚舉中的一個值標識。下面的列表描述了可用的工作階段狀態模式:
- InProc 模式,此模式將工作階段狀態儲存在 Web 服務器上的記憶體中。這是預設設定。注意:它是唯一支援 Session_OnEnd 事件的模式。
- StateServer 模式,此模式將工作階段狀態儲存在一個名為 ASP.NET 狀態服務的單獨進程中。這確保了在重新啟動 Web 應用程式時會保留工作階段狀態,並讓工作階段狀態可用於網路場中的多個 Web 服務器。注意:如果模式設定為 StateServer,則儲存在工作階段狀態中的對象必須是可序列化的。
- SQLServer 模式,將工作階段狀態儲存到一個 SQL Server 資料庫中。這確保了在重新啟動 Web 應用程式時會保留工作階段狀態,並讓工作階段狀態可用於網路場中的多個 Web 服務器。注意:如果是 SQL Server 模式,則儲存在工作階段狀態中的對象必須是可序列化的。
- Custom 模式,此模式允許您指定自訂儲存提供者。
- Off 模式,此模式禁用工作階段狀態。
通過在應用程式的 Web.config 檔案中為 sessionState 元素的 mode 屬性分配一個 SessionStateMode 枚舉值,可以指定要讓 ASP.NET 工作階段狀態使用的模式。除了 InProc 和 Off 之外,其他模式都需要附加參數,例如將在本主題後面討論的連接字串值。通過訪問 System.Web.SessionState.HttpSessionState.Mode 屬性的值,可以查看當前選定的工作階段狀態。*p3
註:
*p3:工作階段狀態模式 http://msdn.microsoft.com/zh-cn/library/ms178586(v=VS.80).aspx
3、ASP.NET在不同應用程式之間共用Session *p4
多個單獨的應用程式,如何將這些模組集中身分識別驗證與授權過程
方案1:
將每個獨立的Web應用程式放到統一的解決方案中,實現起來複雜,易用性不高。
方案2:利用Session會話共用
InProc模式,Session被儲存在IIS進程中,每個虛擬目錄是隔離的,所以無法共用Session。
StateServer 模式,雖然是獨立的狀態伺服器(進程),但在記憶體中這些應用程式還是隔離的。
SQLServer 模式,由於對Session的全部操作都是由預存程序來實現的,而且預存程序未進行加密,可以通過修改預存程序的內部結構來達到共用的目的。
ASPState資料庫ASPStateTempApplications表中儲存的是應用程式資訊,每個應用程式在啟動的時候在這裡會註冊一條記錄,包括應用程式的ID(通過雜湊演算法產生的)和應用程式名稱。有多少個應用程式,在這個表裡就對應多少條記錄。那我們現在要做的是把這些記錄變成一條記錄,也就是要欺騙Framework,讓它認為這些不同的應用程式是同一個應用程式。
TempGetAppID預存程序,這個預存程序是用於通過傳遞應用程式名稱來得到應用程式ID資訊的。每個應用程式在調用這個過程時,這個過程會去AspStateTempApplications中檢查是否有相應的記錄,如果沒有,就插入記錄,然後返回相應的ID。
ALTER PROCEDURE [dbo].[TempGetAppID]
@appName tAppName,
@appId int OUTPUT
AS
SET @appName = LOWER(@appName)
--變數值固定,使所有應用程式通用為一個
SET @appName = '/lm/w3svc/650056020/root/personnel/share'
SET @appId = NULL
SELECT @appId = AppId
FROM [tempdb].dbo.ASPStateTempApplications
WHERE AppName = @appName
註:
*p4:ASP.NET在不同應用程式之間共用Session http://www.3qsoft.com/Article.aspx?ID=173
4、Session無故丟失 *p5
mode="InProc"
==
預設的配置方式很容易丟失Session 請參考
asp中Session的工作原理:
asp的Session是具有進程依賴性的。ASP Session狀態存於IIS的進程中,也就是inetinfo.exe這個程式。所以當inetinfo.exe進程崩潰時,這些資訊也就丟失。另外,重起或者關閉IIS服務都會造成資訊的丟失。
原因1:
bin目錄中的檔案被改寫,asp.net有一種機制,為了保證dll重新編譯之後,系統正常運行,它會重新啟動一次網站進程,這時就會導致Session丟失,所以如果有access資料庫位於bin目錄,或者有其他檔案被系統改寫,就會導致Session丟失
原因2:
檔案夾選項中,如果沒有開啟“在單獨的進程中開啟檔案夾視窗”,一旦建立一個視窗,系統可能認為是新的Session會話,而無法訪問原來的Session,所以需要開啟該選項,否則會導致Session丟失
原因3:
似乎大部分的Session丟失是用戶端引起的,所以要從用戶端下手,看看cookie有沒有開啟
原因4:
Session的時間設定是不是有問題,會不會因為逾時造成丟失
原因5:
IE中的cookie數量限制(每個域20個cookie)可能導致session丟失
原因6:
使用web garden模式,且使用了InProc mode作為儲存session的方式
解決丟失的經驗
1. 判斷是不是原因1造成的,可以在每次重新整理頁面的時候,跟蹤bin中某個檔案的修改時間
2. 做Session讀寫日誌,每次讀寫Session都要記錄下來,並且要記錄SessionID、Session值、所在頁面、當前函數、函數中的第幾次Session操作,這樣找丟失的原因會方便很多
3. 如果允許的話,建議使用state server或sql server儲存session,這樣不容易丟失
4. 在global.asa中加入代碼記錄Session的建立時間和結束時間,逾時造成的Session丟失是可以在SessionEnd中記錄下來的。
5. 如果有些代碼中使用用戶端指令碼,如javascript維護Session狀態,就要嘗試調試指令碼,是不是因為指令碼錯誤引起Session丟失
問:為什麼Session在有些機器上偶爾會丟失?
答:可能和機器的環境有關係,比如:防火牆或者殺毒軟體等,嘗試關閉防火牆。
問:為什麼當調用Session.Abandon時並沒有激發Session_End方法?
答:首先Session_End方法只支援InProc(進程內的)類型的Session。其次要激發Session_End方法,必須存在Session(即系統中已經使用Session了),並且至少要完成一次請求(在這次請求中會調用該方法)。
問:為什麼當我在InProc模式下使用Session會經常丟失?
答:該問題通常是由於應用程式被回收導致的,因為當使用進程內Session時,Session是儲存在aspnet_wp進程中,當該進程被回收Session自然也就沒有了,確定該進程是否被回收可以通過查看系統的事件檢視器獲得資訊。
具體資訊請參考:
Session variables are lost intermittently in ASP.NET applications
http://support.microsoft.com/default.aspx?scid=kb;en-us;Q316148
在1.0的時候也有一個bug會導致背景工作處理序被回收並重啟,該bug已經在1.1和sp2中修複。
關於該bug的詳細資料請參考:
ASP.NET Worker Process (Aspnet_wp.exe) Is Recycled Unexpectedly.
http://support.microsoft.com/default.aspx?scid=kb;en-us;Q321792
問:什麼類型的對象可以儲存在Session裡?
答:這依賴使用的Session的模式,當使用的是進程內(InProc)的Session那麼可以輕鬆的儲存任何對象。如果你使用了非InProc的模式,則只能儲存可以序列化和還原序列化的對象,如果此時儲存的對象不支援序列化,則不能儲存到這種模式(非InProc)的Session裡。
問:為什麼在Session_End中不能使用Response.Redirect和Server.Transfer方法跳轉頁面?
答:Session_End是一個在伺服器內部激發的事件處理函數。它是基於一個伺服器內部的計時器的,在激發該事件時伺服器上並沒有相關的HttpRequest對象,因此此時並不能使用Response.Redirect和Server.Transfer方法。
問:在Session_End中是否可以獲得HttpContext對象?
答:不行,因為這個事件並沒有和任何的請求(Request)相關聯,沒有基於請求的上下文。
問:在Web Service中該如何使用Session?
答:為了在Web Service中使用Session,需要在Web Service的調用方做一些額外的工作,必須儲存和儲存調用Web Service時使用的Cookie。詳細資料請參考MSDN文檔的HttpWebClientProtocol.CookieContainer屬性。然而,如果你使用Proxy 伺服器訪問Web Service由於架構的限制,兩者不能共用Session。
問:當我使用webfarm時,當我重新導向到其他的Web伺服器時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的狀態值,Session是否提供了鎖定機制?
答:Session實現了Reader/Writer的鎖機制:
當頁面對Session具有可寫功能(即頁面有 <%@ Page EnableSessionState="True" %>標記),此時直到請求完成該頁面的Session持有一個寫鎖定。
當頁面對Session具有唯讀功能(即頁面有 <%@ Page EnableSessionState="ReadOnly" %>標記),此時知道請求完成該頁面的Session持有一個讀鎖定。
讀鎖定將阻塞一個寫鎖定;讀鎖定不會阻塞讀鎖定;寫鎖定將阻塞所有的讀寫鎖定。這就是為什麼兩個架構中的同一個頁面都去寫同一個Session時,其中一個要等待另一個(稍快的那個)完成後,才開始寫。
問:Session平滑逾時意味著什嗎?
答:Session平滑逾時意味著只要你的頁面訪問(使用)了Session,逾時時間將被重新整理(可以理解為重新計時),即從該頁面請求開始,將重新計算逾時時間。但是,該頁面不能禁用Session。它會自動的訪問當前頁面的Session,重新整理逾時時間。
問:在global.asax中的事件處理函數中Session為什麼無效?
答:依賴於在哪個事件處理函數中使用Session,Session在AcquireRequestState事件之後才有效,該事件之後的所有事件處理函數都可以使用Session,之前的則不能。
問:當我使用InProc模式儲存Session時,此時的Session是儲存在哪裡?
答:不同的IIS的處理方式不同,
當使用的是IIS5的時候Session是儲存在aspnet_wp.exe的進程空間裡的。
當使用的是IIS6時,預設情況下所有的應用程式共用應用程式集區,Session儲存在w3wp.exe的進程空間中。
問:當頁面出現錯誤後我的Session是否將被儲存?我需要在Session_End中處理一些清理工作,但是失敗了,為什嗎?
答:Session_End只有在Session運行在InProc模式下才會被執行。Session_End使用的帳號是運行aspnet_wp背景工作處理序的帳號(這個可以在machine.config中設定)。因此,如果在Session_End方法裡,使用整合式安全性連結到SQL,它將使用aspnet_wp進程的帳號開啟連結,此時成功與否則依賴於你的SQL的安全性設定。
問:在Session_End是我是否可以獲得有效HttpSessionState和HttpContext對象?
答:你可以在這個方法中獲得HttpSessionState對象,可以直接使用Session來訪問即可。但是不能獲得HttpContext對象,因為該事件並沒有和任何請求相關聯,因此不存在內容物件。
問:在SQLServer模式下使用Session,為什麼我的Session不到期?
答:在SqlServer模式下,Session的到期是通過SQL Agent的註冊工作完成的,請檢查你的SQL Agent是否運行?
問:當我設定EnableSessionState為“ReadOnly”後,但是我在InProc模式下依然可以修改Session的值,這是為什嗎?
答:即使EnableSessionState標示為ReadOnly,但是在InProc模式下使用者依然可以編輯Session。唯一不同的是,在請求過程中Session將不會被鎖住。
問:為什麼在切換成SQLServer模式後我的請求被掛起了?
答:檢查在Session裡面是否都儲存的是可以儲存在SQLServer模式下的對象,即這些對象必須支援序列化。
問:當Session設定成cookieless後會有什麼影響?
答:當把cookieless設定成true時,主要會有下面的約束:
1、在頁面中不能使用絕對連結
2、在應用程式中在除了Http和Https之間的切換時需要完成一些其他的步驟。
如果發送一個連結給其他人,此時的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儲存。關閉當前的IE,開啟一個新IE,重新訪問剛才的Web應用程式,瀏覽器地址就會變為 http://localhost/MyTestApplication/(ulqsek45heu3ic2a5zgdl245)/default.aspx中黑體標出的就是用戶端的Session ID。注意,這段資訊是由IIS自動加上的,不會影響以前正常的串連。 *p6
問:當Session設定成cookieless後會有什麼影響?
答:當把cookieless設定成true時,主要會有下面的約束:
1、在頁面中不能使用絕對連結
2、在應用程式中在除了Http和Https之間的切換時需要完成一些其他的步驟。
如果發送一個連結給其他人,此時的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內容, ex: Session["xxx"]=123 , 您會發現ID就會固定. *p8
註:
*p8:[ASP.Net]Session.IsNewSession與Session.SessionID http://www.dotblogs.com.tw/yilinliu/archive/2009/04/24/8163.aspx