介紹ASP.NET 中的SESSION如何實現
在ASP.NET中,狀態的保持方法大致有:
ApplicationState,SessionState,Cookie,配置文件,緩存。
【ApplicationState】 的典型應用如存儲全局數據。
【SessionState】 的典型應用如購物車項目保存。
【Cookie】 的典型應用如網站的個性化設置。
【配置文件】 的典型應用如保存客戶賬戶信息。
【緩存】 的典型應用如保存從數據庫獲取的數據。
相對來講,最不安全的是Cookie,因為它存儲在客戶端,會被用戶修改。其它另外幾種都只是在服務端,從來沒被傳送到客戶端,所以是安全的。但是對于Session來說,因為涉及到一個SessionID的問題,如果不使用SSL(Secure Socket Layer)協議(https就基于SSL)的話,可能發生 會話劫持問題。當然,上面提到的一個狀態保持是一個比較廣義的狀態保持,真正能保持特定客戶端的狀態的,只有Cookie 與 Session兩種,當然其它基于登錄用戶的方式就不提了。
今天我先只學習Session吧,前幾天筆試時,Session 上吃了大虧。Session可以在服務器端保持一些信息,并且當一個特定的用戶在一個特定的WebApp中的不同頁面間跳轉時,這個信息是可以共享的。所以,這種機制就常被拿來保存購物車信息,因為一個用戶在一個電子商務站點,可能會依次瀏覽不同的商品頁面,然后往里面加商品,剛好是針對同一用戶的頁面跳轉信息保持,正好用Session實現。那么對于Server端來說,要標識一個特定的客戶端,就要給客戶端一個ID,叫做 SessionID。這個東西要由服務端生成然后發送,存放在客戶端,存放方式有兩種,一種是客戶端 Cookie,另一種是附加在URL上。就是因為這個步驟,導致了前面所謂的會話劫持的風險。這種風險可由使用SSL傳送來解決。
關于SessionID,需要知道的是,它由HTTP REQUEST處理管道中的一個叫SessionStateModule的模塊產生的一個
120位的標識符,并使用一個私有算法來生成的,保證了該值是唯一的且足夠隨機(當然是從統計學的角度來說)。因此從這兒可以看出,SessionID完全不用開發人員操心,那是ASP.NET服務解決的問題。接下來,系統提供了一個名叫 Session 的集合,可以直接進行讀寫操作,如下所示:
寫入:Session["SimpleString"] = "Hello Session!";
在本頁面,或者下一個頁面中讀取:
string s = Session["SimpleString"].ToString(); //注意這兒要對集合元素進行類型轉化。
真是太簡單了。本著深入理解一樣事物的原則,我當然要弄明白,這個Session倒底是個什么東西,以及這些Session信息,倒底是放在服務器上的哪兒的?
1:Session 是 HttpContext 類的一個屬性(Property),是一個HttpSessionState 類型的對象:
public sealed class HttpContext : IServiceProvider
{
//
public HttpSessionState Session { get; }
//
}
既然它是一個HttpSessionState類型的對象,那我看看這個類倒底提供了哪些東西可用,查了下MSDN,有很多東西,但我想比較有趣的有:
Session.Count 指示當前會話集合中的項目數。
Session.SessionID 指示當前客戶端會話的SessionID。
IsCookieless 指示當前會話ID是存儲在cookie中還是嵌入在URL中。
Timeout 指示了當前會話要保存多長時間,因為客戶端不會請求銷毀Session數據,所以這些數據要等一定的時間后 自動由服務端釋放。
Abandon() 使用該方法可以立即取消當前會話并釋放它戰勝的空間,在退出頁面中它很有效,能夠確保服務器資源最快得 到回收。
Clear() 該方法在不改變當前會話ID的情況下清空所有的會話項目。
2:Session數據也是由SessionStateModule這個模塊來負責處理的,但它并不保存會話數據,數據是放在稱做SessionState Provider 的東西中的,有三種典型的Provider 方式:InProc ,StateServer,SQLServer 。
InProc: 設置為將Session存儲在進程內,跟ASP中的存儲方式一樣,這是默認值。
StateServer :設置為將Session存儲在獨立的狀態服務中。
SQLServer: 設置將Session存儲在sql server中。
我們一般默認使用InProc方式,這個配置是通過web.config來指定的,如下:
<sessionState
mode="InProc"
stateConnectionString="tcpip=127.0.0.1:42424"
sqlConnectionString="data source=127.0.0.1;Trusted_Connection=yes"
cookieless="false"
timeout="20"
/>
這一個配置節的語法如下:
"Off|InProc|StateServer|SQLServer"
cookieless="true|false"
timeout="number of minutes"
stateConnectionString="tcpip=server:port"
sqlConnectionString="sql connection string"
stateNetworkTimeout="number of seconds"
/>
另外兩種存儲方法要具體配置,參考下面的那篇列舉的文章即可。
最后一個學習點:Session信息什么情況下會不可用。
1:用戶關閉并重啟瀏覽器,這時候再請求同一個頁面,盡管Session仍然在,但是因為這次又生成了新的SessionID,所以舊的Session已經不可用了。
2:用戶通過另一個瀏覽器窗口訪問在同一頁面,這時候不同的瀏覽器有不同的處理方法,有些Session仍然可用,有些不可用。
3:由于沒有活動導致會話超時,默認情況下是20分鐘閑置后就會超時。
4:程序中調用了Session.Abandon()方法結束了會話。