Session 用法


一.關於Session,SessionID和Cookies

Session數據保存在服務器端, 但是每一個客戶端都需要保存一個SessionID, SessionID保存在Cookies中, 關閉瀏覽器時過期.

在向服務器發送的HTTP請求中會包含SessionID, 服務器端根據SessionID獲取獲取此用戶的Session信息.

很多初級開發人員不知道SessionID和Cookies的關係, 所以常常認爲兩者沒有聯繫. 這是不正確的. 正是因爲SessionID保存在Cookies中, 所以在我們保存Cookies的時候,一定要注意不要因爲Cookies的大小和個數問題而導致SessionID對象. 在我們的程序中, 對SessionID的Cookies有特殊的處理:

         /// <summary>
        /// 寫入cookie.
        /// </summary>
        /// <param name="day"></param>
        /// <returns></returns>
        public bool SetCookie(int day)
        {            string CookieName = GetType().ToString();
            HttpCookie SessionCookie = null;            //對 SessionId 進行備份.
            if (HttpContext.Current.Request.Cookies["ASP.NET_SessionId"] != null)
            {                string SesssionId = HttpContext.Current.Request.Cookies["ASP.NET_SessionId"].Value.ToString();
                SessionCookie = new HttpCookie("ASP.NET_SessionId");
                SessionCookie.Value = SesssionId;

            }
            //省略掉中間的代碼部分.只保留備份SessionID和找回SessionID的邏輯
            

            //如果cookie總數超過20 個, 重寫ASP.NET_SessionId, 以防Session 丟失.
            if (HttpContext.Current.Request.Cookies.Count > 20 && SessionCookie != null)
            {                if (SessionCookie.Value != string.Empty)
                {        
                    HttpContext.Current.Response.Cookies.Remove("ASP.NET_SessionId");
                    HttpContext.Current.Response.Cookies.Add(SessionCookie);
                }
            }            return true;
        }

   二.搭建Session服務器的幾種方式

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

方式名稱    存儲方式

1.Off   設置爲不使用Session功能

2.InProc  設置爲將Session存儲在進程內,就是ASP中的存儲方式,這是默認值。

3.StateServer  設置爲將Session存儲在獨立的狀態服務中。通常是aspnet_state.exe進程.

4.SQLServer  設置將Session存儲在SQL Server中。

5.Customer  自定製的存儲方案

  三.使用 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中, 我們需要修改 <configuration> / <system.web> 的<sessionState>節點.如果沒有

沒有則添加(默認使用的是InProc方式)

<sessionState mode="StateServer" stateConnectionString="tcpip=服務器ip:42424" cookieless="false" timeout="60"/>

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

四.使用經驗與技巧總結

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

(1)StateServer模式:

1.在web farm中,請確認在所有的web服務器上有相同的<machineKey>

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):

        <httpModules>
            ...
            <add name="Session" type="System.Web.SessionState.SessionStateModule"/>
            ...
        </httpModules>

確認此模塊是否存在.

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

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

<machineKey validationKey="1234567890123456789012345678901234567890AAAAAAAAAA" decryptionKey="123456789012345678901234567890123456789012345678" validation="SHA1" decryption="Auto" />

(2)SqlServer模式:

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

2. 如果使用了默認是數據庫, 則在客戶端配置文件中的數據庫鏈接字符串的用戶,需要擁有ASPState和tempdb兩個庫的dbowner權限.

3. 在SQLServer模式下,session過期是由SQL Agent使用一個註冊任務完成的,要確認SQL Agent已經運行。否則無法清理過期的Session數據, 會導致數據庫數據一直增加.

4. 如果使用SqlServer模式時, 對於Web場中的各服務器的 ASP.NET 應用程序路徑必須是相同的。請在 IIS 配置數據庫中對 Web 場中的所有 Web 服務器進行 Web 站點的應用程序路徑同步。大小寫一定要相同,因爲 Web 站點的應用程序路徑是區分大小寫的。

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

<machineKey validationKey="1234567890123456789012345678901234567890AAAAAAAAAA" decryptionKey="123456789012345678901234567890123456789012345678" validation="SHA1" decryption="Auto" />

(3)Session:

1. 不能直接通過Session服務器在ASP.NET和ASP之間共享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屬性即可:

    <sessionState
      cookieless="UseUri"
      />
 

2. 一般在Session超時或刪除之後,SessionID保持不變. 因爲Session過期後會在服務器端清除數據, 但是SessionID保存在用戶瀏覽器上, 所以只要瀏覽器不關閉則HTTP頭中的SessionID保持不變.

3.關閉瀏覽器後再訪問, SessionID會不同.

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

5.FireFox的標籤頁和新的FireFox窗口, SessionID都相同, 在FF的窗口和標籤頁上Session能共享.

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

<frameset cols="25%,50%,25%">
  <frame src="SessionID.aspx">
  <frame src="SessionID.aspx">
  <frame src="SessionID.aspx"></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由一個後臺線程觸發,使用工作者進程賬號運行. 所以程序不會通知發生的錯誤.

5. 在Session_End訪問數據庫要考慮權限問題. Session_End是用運行工作者進程(aspnet_wp.exe)的帳號運行的,這個賬號可以在machine.config中指定。因此,在Session_End中,如果使用integrity security連接SQL,它將使用工作者進程賬號身份連接,這可能會引起登錄失敗.

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



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章