aspnet中的cookie工作機制

簡介

  Cookie 爲 Web 應用程序保存用戶相關信息提供了一種有用的方法。例如,當用戶訪問您的站點時,您可以利用 Cookie 保存用戶首選項或其他信息,這樣,當用戶下次再訪問您的站點時,應用程序就可以檢索以前保存的信息。

  本文概要介紹 Cookie 在 ASP.NET 應用程序中的應用,爲您展示在 ASP.NET 中應用 Cookie 的技術細節,例如編寫 Cookie、然後再讀取它們。同時,還將爲您介紹 Cookie 的各種特性和各種特殊情況,以及 ASP.NET 對 Cookie 的支持。

  什麼是 Cookie?

  Cookie 是一小段文本信息,伴隨着用戶請求和頁面在 Web 服務器和瀏覽器之間傳遞。用戶每次訪問站點時,Web 應用程序都可以讀取 Cookie 包含的信息。

  假設在用戶請求訪問您的網站 www.contoso.com 上的某個頁面時,您的應用程序發送給該用戶的不僅僅是一個頁面,還有一個包含日期和時間的 Cookie。用戶的瀏覽器在獲得頁面的同時還得到了這個 Cookie,並且將它保存在用戶硬盤上的某個文件夾中。

  以後,如果該用戶再次訪問您站點上的頁面,當該用戶輸入 URL www.contoso.com 時,瀏覽器就會在本地硬盤上查找與該 URL 相關聯的 Cookie。如果該 Cookie 存在,瀏覽器就將它與頁面請求一起發送到您的站點,您的應用程序就能確定該用戶上一次訪問站點的日期和時間。您可以根據這些信息向用戶發送一條消息,也可以檢查過期時間或執行其他有用的功能。

  Cookie 是與 Web 站點而不是與具體頁面關聯的,所以無論用戶請求瀏覽站點中的哪個頁面,瀏覽器和服務器都將交換 www.contoso.com 的 Cookie 信息。用戶訪問其他站點時,每個站點都可能會向用戶瀏覽器發送一個 Cookie,而瀏覽器會將所有這些 Cookie 分別保存。

  以上就是 Cookie 的基本工作原理。那麼,Cookie 有哪些用途呢?最根本的用途是 Cookie 能夠幫助 Web 站點保存有關訪問者的信息。更概括地說,Cookie 是一種保持 Web 應用程序連續性(即執行“狀態管理”)的方法。瀏覽器和 Web 服務器除了在短暫的實際信息交換階段以外總是斷開的,而用戶向 Web 服務器發送的每個請求都是單獨處理的,與其他所有請求無關。然而在大多數情況下,都有必要讓 Web 服務器在您請求某個頁面時對您進行識別。例如,購物站點上的 Web 服務器跟蹤每個購物者,以便站點能夠管理購物車和其他的用戶相關信息。因此 Cookie 的作用就類似於名片,它提供了相關的標識信息,可以幫助應用程序確定如何繼續執行。

  使用 Cookie 能夠達到多種目的,所有這些目的都是爲了使 Web 站點記住您。例如,一個實施民意測驗的站點可以簡單地利用 Cookie 作爲布爾值,表示您的瀏覽器是否已經參與了投票,從而避免您重複投票; 而那些要求用戶登錄的站點則可以通過 Cookie 來確定您是否已經登錄過,這樣您就不必每次都輸入憑據。

  有關 Cookie 的更多背景信息,建議您閱讀 Verizon Web 站點中的“How Internet Cookies Work”一文,地址爲 http://www22.verizon.com/about/community/learningcenter/articles/displayarticle1/0,4065,1022z1,00.html(英文)。其作者詳細解釋了什麼是 Cookie 以及 Cookie 是如何在瀏覽器和服務器之間交換信息的,他還全面總結了 Cookie 涉及的隱私問題。

  順便問一下,您是否想知道它們爲什麼被稱作“Cookie”?Jargon File(又稱爲“The New Hacker''s Dictionary”)版本 4.3.3 對這一術語的詞源給出了準確的定義和合理的解釋。您可以在 http://www.catb.org/~esr/jargon/jargon.html#cookie(英文)找到相關的條目。

  在此後的內容中,本文將假設您已經知道什麼是 Cookie,並且假設您已經清楚爲什麼要在 ASP.NET 應用程序中使用 Cookie。

--------------------------------------------------------

Cookie 的限制

  在開始討論 Cookie 的技術細節之前,我想先介紹一下 Cookie 應用的幾條限制。大多數瀏覽器支持最多可達 4096 字節的 Cookie,如果要將爲數不多的幾個值保存到用戶計算機上,這一空間已經足夠大,但您不能用一個 Cookie 來保存數據集或其他大量數據。在實際應用中,您可能並不希望在 Cookie 中保存大量的用戶信息,而只希望保存用戶編號或其他標識符。之後,當用戶再次訪問您的站點時,您就可以使用該用戶 ID 在數據庫中查找用戶的詳細信息。(有關保存用戶信息的說明,請參閱 Cookie 和安全性。)

  瀏覽器還限制了您的站點可以在用戶計算機上保存的 Cookie 數。大多數瀏覽器只允許每個站點保存 20 個 Cookie。如果試圖保存更多的 Cookie,則最先保存的 Cookie 就會被刪除。還有些瀏覽器會對來自所有站點的 Cookie 總數作出限制,這個限制通常爲 300 個。

  您最可能遇到的 Cookie 限制是:用戶可以設置自己的瀏覽器,拒絕接受 Cookie。您很難解決這個問題,除非完全不使用 Cookie 而是通過其他機制來保存用戶相關信息。保存用戶信息的一種常用方法是會話狀態,但會話狀態又依賴於 Cookie。這一點在後面的 Cookie 和會話狀態中闡述。

  注意:有關狀態管理和 Web 應用程序中用於保存信息的選項的詳細信息,請參閱 Introduction to Web Forms State(英文)和 State Management Recommendations(英文)。
更一般的經驗很可能是,儘管 Cookie 在應用程序中非常有用,應用程序也不應該依賴於能夠保存 Cookie。利用 Cookie 可以做到錦上添花,但不要利用它們來支持關鍵功能。如果您的應用程序必須使用 Cookie,則您可以通過測試來確定瀏覽器是否接受 Cookie。我在本文後面的檢查瀏覽器是否接受 Cookie 一節中簡單介紹了一種測試方法。

  編寫 Cookie

  您可以利用頁面的 Response(英文)屬性來編寫 Cookie,該屬性提供的對象使用戶可以將信息添加到由頁面向瀏覽器呈現的信息中。Response 對象支持一個名爲 Cookies(英文)的集合,您可以向其中添加要寫入瀏覽器的 Cookie。

  注意:下面要討論的 Response 對象和 Request 對象分別是包含 HttpResponse(英文)和 HttpRequest(英文)類實例的頁面的屬性。要在文檔中查找 Response 和 Request 的信息,請參閱 HttpResponse 和 HttpRequest 下的內容。

  在創建 Cookie 時,您需要指定幾個值。最初,您要指定 Cookie 的名稱和其中保存的值。您可以創建多個 Cookie,每個 Cookie 都必須具有唯一的名稱,以便日後讀取時識別。(Cookie 是按名稱保存的,所以如果您創建了兩個名稱相同的 Cookie,後保存的那一個將覆蓋前一個。)

  您可能還希望指定 Cookie 的過期日期和時間。Cookie 一般都寫入到用戶的磁盤,然後可能一直都留在磁盤上。因此,您可以指定 Cookie 過期的日期和時間。當用戶再次訪問您的站點時,瀏覽器會先檢查您站點的 Cookie 集合,如果某個 Cookie 已經過期,瀏覽器不會把這個 Cookie 隨頁面請求一起發送給服務器,而是刪除這個已經過期的 Cookie。(您的站點可能已經在用戶計算機上寫入了多個 Cookie,每個 Cookie 都有各自的過期日期和時間。) 請注意,由瀏覽器負責管理硬盤上的 Cookie,這將影響您在應用程序中對 Cookie 的使用,我很快會介紹這方面的內容。

  一個 Cookie 的有效期應爲多長?這取決於 Cookie 的用途,換句話說,取決於您的應用程序需要 Cookie 值保持有效的時間有多長。如果利用 Cookie 統計網站的訪問者,您可以把有效期設置爲 1 年,如果某個用戶已有一年時間未訪問您的站點,則可以把該用戶當作新的訪問者; 如果利用 Cookie 來保存用戶的首選項,則可以把其設置爲永遠有效(例如 50 年後到期),因爲定期重新設置首選項對用戶而言是比較麻煩的。有時,您可能需要編寫在數秒或數分鐘內即過期的 Cookie。在本文後面的檢查瀏覽器是否接受 Cookie 一節中,我列舉了一個示例,該示例中創建的 Cookie 的實際有效期就只有幾秒。

  注意:不要忘記用戶隨時可以刪除自己計算機上的 Cookie,所以即使您保存了長期有效的 Cookie,用戶也可以自行決定將其全部刪除,同時清除保存在 Cookie 中的所有設置。

  如果沒有設置 Cookie 的有效期,還是可以創建 Cookie,但它不會保存到用戶的硬盤上,而是會成爲用戶會話信息的一部分。如果用戶關閉瀏覽器或會話超時,該 Cookie 就會被刪除。這種非永久性的 Cookie 很適合用來保存只需短時間保存的信息,或者保存由於安全原因不應該寫入客戶計算機磁盤的信息。例如,如果用戶使用的是一臺公用計算機,而您不希望把 Cookie 寫入這種計算機的磁盤上,這時就可以使用非永久性的 Cookie。

  您可以通過多種方法把 Cookie 添加到 Response.Cookies 集合中。以下示例介紹了兩種完成此任務的方法:

Response.Cookies("userName").Value = "mike"
Response.Cookies("userName").Expires = DateTime.Now.AddDays(1)

Dim aCookie As New HttpCookie("lastVisit")
aCookie.Value = DateTime.Now.ToString
aCookie.Expires = DateTime.Now.AddDays(1)
Response.Cookies.Add(aCookie)

  該示例向 Cookies 集合中添加了兩個 Cookie,一個稱爲“userName”,另一個稱爲“lastVisit”。對於第一個 Cookie,我直接設置了 Response.Cookies 集合的值。您可以使用這種方法向集合中添加值,因爲 Response.Cookies 是從 NameObjectCollectionBase(英文)類型的特殊集合派生得到的。

  對於第二個 Cookie,我創建了 Cookie 對象的一個實例(HttpCookie [英文] 類型),並設置了其屬性,然後通過 Add 方法把它添加到 Response.Cookies 集合。實例化 HttpCookie 對象時,您必須把 Cookie 名稱作爲構造函數的一部分進行傳遞。

  這兩個示例完成了相同的任務,即向瀏覽器寫入一個 Cookie。您要採用哪種方法主要取決於您的個人喜好。您可能會發現第二種方法在設置 Cookie 屬性方面要稍微容易一些,但同時您也會注意到兩者的差別並不是很大。

  在這兩種方法中,有效期值必須爲 DateTime 類型。而“lastVisited”值也是日期/時間值。但在這種情況下,我必須把日期/時間值轉換爲字符串,因爲 Cookie 中的任何值最終都是以字符串的形式保存的。

查看您的 Cookie

  您可能會發現,瞭解創建 Cookie 的效果會對您很有幫助。而查看 Cookie 是比較容易的,因爲它們都是文本文件,關鍵在於您能找到它們。不同的瀏覽器保存 Cookie 的方式也不同。我將介紹 Internet Explorer 是如何保存 Cookie 的。如果您使用的是其他瀏覽器,請查看該瀏覽器的幫助,以瞭解有關 Cookie 處理方面的知識。

  查看 Cookie 的一個簡便方法是讓 Internet Explorer 爲您查找。在 Internet Explorer 中,從“工具”菜單中選擇“Internet 選項”,在“常規”選項卡中單擊“設置”,然後單擊“查看文件”。Internet Explorer 將打開一個窗口,顯示所有的臨時文件,包括 Cookie。在窗口中查找以“Cookie:”開頭的文件 或查找文本文件。雙擊一個 Cookie,在默認的文本文件中打開它。

  您也可以在硬盤上查找 Cookie 的文本文件,從而打開 Cookie。Internet Explorer 將站點的 Cookie 保存在文件名格式爲 @.txt 的文件中,其中 是您的帳戶名。例如,如果您的名稱爲 mikepope,您訪問的站點爲 www.contoso.com,那麼該站點的 Cookie 將保存在名爲 [email protected] 的文件中。(該文件名可能包含一個順序的編號,如 [email protected][1].txt。)

  這個 Cookie 文本文件是與用戶相關的,所以會按照帳戶分別保存。例如,在 Windows XP 中,您可以在如下所示的目錄中找到 Cookie 文件:

c:/Documents and Settings//Cookies

  要查找最新創建的 Cookie,可以按修改日期對目錄內容進行排序,並查找最近修改的文件。

  您可以使用文本編輯器打開 Cookie。如果該文件包含多個 Cookie,這些 Cookie 之間將用星號 (*) 分隔。每個 Cookie 的第一行是 Cookie 的名稱,第二行是值,其餘各行則包含 Cookie 的日常處理信息,例如過期日期和時間。Cookie 中還有一個簡單的校驗和,如果更改 Cookie 名稱或值的長度,瀏覽器就會檢測到修改並刪除該 Cookie。

  多值 Cookie(子鍵)

  以上示例爲每個要保存的值(用戶名、上次訪問時間)都使用了一個 Cookie 。您也可以在一個 Cookie 中保存多個名稱/值對。名稱/值對也稱作“鍵”或“子鍵”,具體取決於您讀取的內容。(如果您熟悉 URL 的結構,就會發現子鍵與其中的查詢字符串非常相象。) 例如,如果不希望創建名爲“userName”和“lastVisit”的兩個單獨的 Cookie,可以創建一個名爲“userInfo”的 Cookie,並使其包含兩個子鍵:“userName”和“lastVisit”。

  有很多原因會讓我們用子鍵來代替單獨的 Cookie。最顯而易見的是,把相關或類似的信息放在一個 Cookie 中會比較有條理。另外,由於所有信息都在一個 Cookie 中,所以諸如有效期之類的 Cookie 屬性就適用於所有信息。(當然,如果要爲不同類型的信息指定不同的過期日期,就應該把信息保存在單獨的 Cookie 中。)

  帶有子鍵的 Cookie 還可以幫助您減小 Cookie 的大小。如前面的 Cookie 的限制一節所述,Cookie 的總大小限制在 4096 字節以內,而且不能爲一個網站保存超過 20 個 Cookie。利用帶子鍵的單個 Cookie,站點的 Cookie 數量就不會超過 20 個的限制。此外,一個 Cookie 會佔用大約 50 個字符的基本空間開銷(用於保存有效期信息等),再加上其中保存的值的長度,其總和接近 4K 的限制。如果使用五個子鍵而不是五個單獨的 Cookie,您可以省去四個 Cookie 的基本空間開銷,總共能節省大約 200 個字節。

  要創建帶子鍵的 Cookie,您可以使用用於編寫單個 Cookie 的各種語法。以下示例顯示了編寫同一 Cookie 的兩種不同方法,其中的每個 Cookie 都帶有兩個子鍵:

Response.Cookies("userInfo")("userName") = "mike"
Response.Cookies("userInfo")("lastVisit") = DateTime.Now.ToString
Response.Cookies("userInfo").Expires = DateTime.Now.AddDays(1)

Dim aCookie As New HttpCookie("userInfo")
aCookie.Values("userName") = "mike"
aCookie.Values("lastVisit") = DateTime.Now.ToString
aCookie.Expires = DateTime.Now.AddDays(1)
Response.Cookies.Add(aCookie)

  控制 Cookie 有效範圍

  默認情況下,一個站點的全部 Cookie 都一起保存在客戶機上,而且所有這些 Cookie 都會隨着對該站點發送的請求一起發送到服務器,也就是說,站點的每個頁面都能得到該站點的所有 Cookie。但有時候,您可能希望 Cookie 更具有針對性,這時,您可以通過兩種方法設置 Cookie 的有效範圍:

  把 Cookie 的有效範圍限制在服務器上的一個文件夾中,實際上這樣就將 Cookie 限制到站點上的某個應用程序。

  把有效範圍設置爲某個域,從而允許您指定域中的哪些子域可以訪問 Cookie。

  將 Cookie 限制到某個文件夾或應用程序

  要將 Cookie 限制到服務器上的某個文件夾,請按如下方法設置 Cookie 的 Path 屬性:

Dim appCookie As New HttpCookie("AppCookie")
appCookie.Value = "written " & Now.ToString
appCookie.Expires = Now.AddDays(1)
appCookie.Path = "/Application1"
Response.Cookies.Add(appCookie)

  當然,您也可以通過直接設置 Response.Cookies 來編寫 Cookie,如前文所述。

  路徑可以是站點根目錄下的物理路徑,也可以是虛擬根目錄。這樣一來,Cookie 就只能用於 Application1 文件夾或虛擬根目錄中的頁面。例如,如果您的站點名爲 www.contoso.com,則前面示例中生成的 Cookie 就只能用於路徑爲 http://www.contoso.com/Application1/ 的頁面以及該文件夾下的所有頁面,而不適用於其他應用程序中的頁面,如 http://www.contoso.com/Application2/ 或 http://www.contoso.com/ 下的頁面。

  提示:通過對 Internet Explorer 和 Mozilla 瀏覽器進行測試發現,此處使用的路徑是區分大小寫的。一般而言,Windows 服務器上的 URL 不區分大小寫,但這種情況例外。您無法控制用戶如何在瀏覽器中輸入 URL,但是,如果您的應用程序依賴於與特定路徑相關的 Cookie,則請確保您所創建的所有超鏈接中的 URL 與 Path 屬性值的大小寫相匹配。

  將 Cookie 的有效範圍限制到域

  默認情況下,Cookie 與特定的域相關聯。例如,如果您的站點是 www.contoso.com,那麼當用戶向該站點請求頁面時,您編寫的 Cookie 就被髮送到服務器。(有特定路徑值的 Cookie 除外,我在上一節剛剛解釋過。) 如果您的站點有子域(例如 contoso.com、sales.contoso.com 和 support.contoso.com),就可以把 Cookie 同特定的子域相關聯。爲此,需要設置 Cookie 的 Domain 屬性,如下所示:

Response.Cookies("domain").Value = DateTime.Now.ToString
Response.Cookies("domain").Expires = DateTime.Now.AddDays(1)
Response.Cookies("domain").Domain = "support.contoso.com"

  如果按照這種方式設置域,則 Cookie 只能用於指定子域中的頁面。

  您也可以利用 Domain 屬性來創建可在多個子域中共享的 Cookie。例如,對域進行如下設置:

Response.Cookies("domain").Value = DateTime.Now.ToString
Response.Cookies("domain").Expires = DateTime.Now.AddDays(1)
Response.Cookies("domain").Domain = "contoso.com"

  這樣,該 Cookie 就可用於主域、sales.contoso.com 和 support.contoso.com。

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