ASP.NET 工作階段狀態概觀

更新:2007 年 11 月

使用 ASP.NET 工作階段狀態為使用者儲存和擷取值。

這個主題包含:

  • 背景

  • 程式碼範例

  • 類別參考

背景

當使用者巡覽 Web 應用程式中的 ASP.NET 頁面時,ASP.NET 工作階段狀態可讓您為使用者儲存和擷取值。HTTP 是沒有狀態 (Stateless) 的通訊協定。這表示 Web 伺服器會將頁面的每個 HTTP 要求視為獨立要求。伺服器不會保留先前要求所使用的變數值。ASP.NET 工作階段狀態會在限制時間間隔內,將來自相同瀏覽器的要求識別為一個工作階段,並提供方法來保存這個工作階段期間內的變數值。依照預設,所有 ASP.NET 應用程式都會啟用 ASP.NET 工作階段狀態。

工作階段狀態的替代方案包括下列各項:

  • 應用程式狀態,可儲存所有 ASP.NET 應用程式使用者可以存取的變數。

  • 設定檔屬性,可將使用者值保存在資料存放區中而不使它們逾期。

  • ASP.NET 快取,可將值儲存在適用於所有 ASP.NET 應用程式的記憶體中。

  • 檢視狀態,可保存頁面中的數值。

  • Cookie。

  • HTML 表單上的查詢字串和欄位,可由 HTTP 要求提供。

如需比較不同的狀態管理選項,請參閱 ASP.NET 狀態管理建議事項

工作階段變數

工作階段變數會存放在經由 HttpContext.Session 屬性所公開的 SessionStateItemCollection 物件中。在 ASP.NET 頁面中,目前的工作階段變數會透過 Page 物件的 Session 屬性公開。

工作階段變數集合是以變數名稱或整數索引進行索引。工作階段變數會依名稱參考工作階段變數而建立。您不需要宣告工作階段變數或明確將其加入集合中。下列範例說明如何在 ASP.NET 頁面中建立工作階段變數,以表示使用者的姓氏和名字,並將使用者的姓名設定為擷取自 TextBox 控制項的值。

Session("FirstName") = FirstNameTextBox.Text
Session("LastName") = LastNameTextBox.Text
Session["FirstName"] = FirstNameTextBox.Text;
Session["LastName"] = LastNameTextBox.Text;

工作階段變數可以是任何有效的 .NET 架構型別。下列範例將 ArrayList 物件儲存在名為 StockPicks 的工作階段變數中。當您從 SessionStateItemCollection 擷取 StockPicks 工作階段變數所傳回的值時,該值必須轉換成適當的型別。

' When retrieving an object from session state, cast it to 
' the appropriate type.
Dim stockPicks As ArrayList = CType(Session("StockPicks"), ArrayList)

' Write the modified stock picks list back to session state.
Session("StockPicks") = stockPicks
// When retrieving an object from session state, cast it to 
// the appropriate type.
ArrayList stockPicks = (ArrayList)Session["StockPicks"];

// Write the modified stock picks list back to session state.
Session["StockPicks"] = stockPicks;
注意事項:

當您使用工作階段狀態模式而非 InProc 時,工作階段變數型別必須為基本 .NET 型別或可序列化的。這是因為工作階段變數值會儲存在外部資料存放區中。如需詳細資訊,請參閱工作階段狀態模式

工作階段識別項

工作階段是由唯一的識別項所識別,您可以使用 SessionID 屬性讀取這個識別項。當啟用 ASP.NET 應用程式的工作階段狀態時,應用程式中對頁面的每個要求,都會檢查瀏覽器送出的 SessionID 值。如果並未提供任何 SessionID 值,ASP.NET 會啟動新的工作階段,然後將該工作階段的 SessionID 值與回應一起傳送給瀏覽器。

依照預設,SessionID 值會儲存在 Cookie 中。但是,您也可以設定應用程式,將 "cookieless" 工作階段的 SessionID 值儲存在 URL 中。

只要使用相同的 SessionID 值持續產生要求,工作階段就會視為使用中。如果特定工作階段的要求間隔超過指定的逾時值 (分鐘數),則工作階段會視為已過期。利用過期的 SessionID 值提出要求,會產生新的工作階段。

安全性注意事項:

不管是做為 Cookie 或 URL 的一部分,都會以純文字方式傳送 P:System.Web.SessionState.HttpSessionState.SessionID 值。透過取得 SessionID 值並將該值包含在對伺服器的要求中,惡意使用者可以取得其他使用者的工作階段存取權限。如果您在工作階段狀態中儲存機密資訊,則建議使用 SSL 來加密瀏覽器和伺服器之間包含 SessionID 值的任何通訊內容。

Cookieless SessionID

依照預設,SessionID 值會儲存在瀏覽器中未逾期的工作階段 Cookie 中。但是,您也可以將 Web.config 檔案中 sessionState 區段的 cookieless 屬性設定為 true,以指定不要在 Cookie 中儲存工作階段識別項。

下列範例顯示設定 ASP.NET 應用程式以使用 Cookieless 工作階段識別項的 Web.config 檔案。

<configuration>
  <system.web>
    <sessionState cookieless="true"
      regenerateExpiredSessionId="true" />
  </system.web>
</configuration>

ASP.NET 透過自動將唯一工作階段 ID 插入至頁面的 URL 中,即可維護 Cookieless 工作階段狀態。例如,ASP.NET 已修改下列 URL,以包含唯一工作階段 ID lit3py55t21z5v55vlm25s55:

http://www.example.com/(S(lit3py55t21z5v55vlm25s55))/orderform.aspx

當 ASP.NET 傳送頁面至瀏覽器時,它將工作階段 ID 內嵌於連結中,修改使用應用程式相對路徑之頁面上的所有連結 (不會修改使用絕對路徑的連結)。工作階段作業狀態會一直保留,直到使用者按到以此方式修改的連結為止。但是,如果用戶端重寫了應用程式提供的 URL,ASP.NET 可能就無法解析工作階段 ID 並將要求與現有工作階段產生關聯。在這種情況下,將為要求啟動新的工作階段。

工作階段 ID 會內嵌在 URL 中:在應用程式名稱的斜線之後,並在其餘檔案或虛擬目錄識別項之前。這樣可讓 ASP.NET 在涉及要求中的 SessionStateModule 之前,先解析應用程式名稱。

注意事項:

若要提升應用程式的安全性,您應該允許使用者登出應用程式,同時應用程式應該呼叫 Abandon 方法。這樣可降低惡意使用者取得 URL 中的唯一識別項,並使用該唯一識別項擷取儲存在工作階段中之私用使用者資料的可能性。

重新產生逾期的工作階段識別項

依照預設,用於 Cookieless 工作階段中的工作階段 ID 值會回收使用。也就是說,如果是以逾期的工作階段 ID 產生要求,便會使用要求提供的 SessionID 值來啟動新的工作階段。當有多個瀏覽器使用包含 cookieless SessionID 值的連結時,會導致無意間共用工作階段 (如果透過搜尋引擎、電子郵件訊息、或其他程式來傳遞連結,就可能發生這種情形)。您可以藉由設定應用程式不要循環使用工作階段識別項,降低共用工作階段資料的可能性。若要這麼做,則需將 sessionState 組態項目的 regenerateExpiredSessionId 屬性設為 true。在以逾期的工作階段 ID 產生 Cookieless 工作階段要求時,這會產生新的工作階段 ID。

注意事項:

如果以逾期之工作階段 ID 所產生的要求是使用 HTTP POST 方法產生,則當 regenerateExpiredSessionId 為 true 時,任何已張貼的資料都將會遺失。這是因為 ASP.NET 會執行重新導向,以確定瀏覽器在 URL 中有新的工作階段識別項。

自訂工作階段識別項

您可以實作自訂類別來提供及驗證 SessionID 值。若要這麼做,請建立一個繼承 SessionIDManager 類別的類別,然後以您自己的實作來覆寫 CreateSessionIDValidate 方法。如需範例,請參閱 CreateSessionID 方法所提供的範例。

您可以建立實作 ISessionIDManager 介面的類別,來取代 SessionIDManager 類別。例如,您可能具有使用 ISAPI 篩選常式 (Filter) 將唯一識別項和非 ASP.NET 頁面 (例如 HTML 頁面或影像) 產生關聯的 Web 應用程式。您可以實作自訂的 SessionIDManager 類別,以將這個唯一識別項搭配 ASP.NET 工作階段狀態使用。如果自訂的類別支援 Cookieless 工作階段識別項,您必須實作方案以傳送及擷取 URL 中的工作階段識別項。

工作階段模式

ASP.NET 工作階段狀態可支援數種工作階段變數的儲存選項。每個選項會識別為工作階段狀態 Mode 型別。預設行為是將工作階段變數,存放在 ASP.NET 背景工作處理序的記憶體空間內。但是,您也可以指定應該將工作階段狀態,儲存在不同的處理序、SQL Server 資料庫或自訂資料來源中。如果您不想啟用應用程式的工作階段狀態,可以將工作階段模式設定為 Off

如需詳細資訊,請參閱工作階段狀態模式

工作階段事件

ASP.NET 提供兩種事件來協助您管理使用者工作階段。啟動新的工作階段時便會引發 Session_OnStart 事件,當工作階段被放棄或逾期時則會引發 Session_OnEnd 事件。在 ASP.NET 應用程式的 Global.asax 檔中可以指定工作階段事件。

如果工作階段 Mode 屬性設定為預設模式 InProc 以外的值,就不支援 Session_OnEnd 事件。

注意事項:

如果修改 ASP.NET 應用程式的 Global.asax 或 Web.config 檔,啟動應用程式便會重新啟動,而且任何存放在應用程式狀態或工作階段狀態中的值都將遺失。請留意某些防毒軟體可能會更新應用程式之 Global.asax 或 Web.config 檔的最後修改日期和時間。

如需詳細資訊,請參閱工作階段狀態事件

設定工作階段狀態

您可以使用 system.web 組態區段的 sessionState 項目來設定工作階段狀態。您也可以使用 @ Page 指示詞中的 EnableSessionState 值來設定工作階段狀態。

sessionState 項目可讓您指定下列選項:

  • 工作階段用來儲存資料的模式。

  • 工作階段識別項的值在用戶端與伺服器之間傳送的方式。

  • 工作階段的 Timeout 值。

  • 以工作階段 Mode 設定為基礎的支援值。

下列範例顯示 sessionState 項目,該項目可設定應用程式以用於 SQLServer 工作階段模式。它會將 Timeout 值設定為 30 分鐘,並指定將工作階段識別項儲存在 URL 中。

<sessionState mode="SQLServer"
  cookieless="true "
  regenerateExpiredSessionId="true "
  timeout="30"
  sqlConnectionString="Data Source=MySqlServer;Integrated Security=SSPI;"
  stateNetworkTimeout="30"/>

您可以將工作階段狀態模式設定為 Off,停用應用程式的工作階段狀態。如果您只想要停用應用程式特定頁面的工作階段狀態,可以將 @ Page 指示詞中的 EnableSessionState 值設定為 false。EnableSessionState 值也可以設定為 ReadOnly ,以提供對工作階段變數的唯讀存取。

並行要求和工作階段狀態

存取 ASP.NET 工作階段狀態是每一工作階段獨佔的,表示如果兩個不同的使用者同時產生要求,就會同時授與每個不同工作階段的存取權限。但是,如果使用相同的 SessionID 值而讓相同工作階段產生兩個並行要求,第一個要求將會收到對工作階段資訊的獨佔存取。第二個要求只能在完成第一個要求後執行。(如果因為第一個要求超出鎖定逾時而釋出對資訊的獨佔鎖定,第二個工作階段也能取得存取權)。如果 @ Page 指示詞中的 EnableSessionState 值設定為 ReadOnly,則唯讀工作階段資訊的要求並不會導致工作階段資料的獨佔鎖定。但是,工作階段資料的唯讀要求,仍然必須等候工作階段資料的讀寫要求清除所設定的鎖定。

回到頁首

程式碼範例

HOW TO:儲存工作階段狀態的值

HOW TO:讀取工作階段狀態的值

實作工作階段狀態存放區提供者

回到頁首

類別參考

下表列出與 System.Web.SessionState 命名空間中工作階段狀態相關的重要類別。

成員

描述

SessionIDManager

管理 ASP.NET 工作階段狀態的唯一識別項。

SessionStateItemCollection

用來儲存工作階段狀態變數。

回到頁首

請參閱

概念

實作工作階段狀態存放區提供者