隨筆-7  評論-24  文章-102  trackbacks-0

          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屬性。然而,如果你使用代理服務器訪問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


           

           

          posted on 2010-05-10 10:34 黃小二 閱讀(638) 評論(0)  編輯  收藏 所屬分類: ASP.NET
          主站蜘蛛池模板: 景东| 扶绥县| 湖南省| 长宁区| 星座| 深圳市| 余江县| 乌兰县| 长垣县| 左贡县| 绥滨县| 盈江县| 安康市| 满城县| 金溪县| 江川县| 渭南市| 绥江县| 朝阳市| 哈尔滨市| 海城市| 宁海县| 阳原县| 伊吾县| 阳江市| 莱芜市| 女性| 咸阳市| 尤溪县| 稷山县| 平远县| 昔阳县| 紫金县| 庆阳市| 南和县| 台州市| 梁平县| 克东县| 登封市| 团风县| 惠水县|