ASP.NET中Cookie编程的基础知识
一、簡(jiǎn)介
Cookie 為 Web 應(yīng)用程序保存用戶相關(guān)信息提供了一種有用的方法。例如,當(dāng)用戶訪問您的站點(diǎn)時(shí),您可以利用 Cookie 保存用戶首選項(xiàng)或其他信息,這樣,當(dāng)用戶下次再訪問您的站點(diǎn)時(shí),應(yīng)用程序就可以檢索以前保存的信息。
本文概要介紹 Cookie 在 ASP.NET 應(yīng)用程序中的應(yīng)用,為您展示在 ASP.NET 中應(yīng)用 Cookie 的技術(shù)細(xì)節(jié),例如編寫 Cookie、然后再讀取它們。同時(shí),還將為您介紹 Cookie 的各種特性和各種特殊情況,以及 ASP.NET 對(duì) Cookie 的支持。
二、什么是 Cookie?
Cookie 是一小段文本信息,伴隨著用戶請(qǐng)求和頁面在 Web 服務(wù)器和瀏覽器之間傳遞。用戶每次訪問站點(diǎn)時(shí),Web 應(yīng)用程序都可以讀取 Cookie 包含的信息。
假設(shè)在用戶請(qǐng)求訪問您的網(wǎng)站 www.contoso.com 上的某個(gè)頁面時(shí),您的應(yīng)用程序發(fā)送給該用戶的不僅僅是一個(gè)頁面,還有一個(gè)包含日期和時(shí)間的 Cookie。用戶的瀏覽器在獲得頁面的同時(shí)還得到了這個(gè) Cookie,并且將它保存在用戶硬盤上的某個(gè)文件夾中。
以后,如果該用戶再次訪問您站點(diǎn)上的頁面,當(dāng)該用戶輸入 URL www.contoso.com 時(shí),瀏覽器就會(huì)在本地硬盤上查找與該 URL 相關(guān)聯(lián)的 Cookie。如果該 Cookie 存在,瀏覽器就將它與頁面請(qǐng)求一起發(fā)送到您的站點(diǎn),您的應(yīng)用程序就能確定該用戶上一次訪問站點(diǎn)的日期和時(shí)間。您可以根據(jù)這些信息向用戶發(fā)送一條消息,也可以檢查過期時(shí)間或執(zhí)行其他有用的功能。
Cookie 是與 Web 站點(diǎn)而不是與具體頁面關(guān)聯(lián)的,所以無論用戶請(qǐng)求瀏覽站點(diǎn)中的哪個(gè)頁面,瀏覽器和服務(wù)器都將交換 www.contoso.com 的 Cookie 信息。用戶訪問其他站點(diǎn)時(shí),每個(gè)站點(diǎn)都可能會(huì)向用戶瀏覽器發(fā)送一個(gè) Cookie,而瀏覽器會(huì)將所有這些 Cookie 分別保存。
以上就是 Cookie 的基本工作原理。那么,Cookie 有哪些用途呢?最根本的用途是 Cookie 能夠幫助 Web 站點(diǎn)保存有關(guān)訪問者的信息。更概括地說,Cookie 是一種保持 Web 應(yīng)用程序連續(xù)性(即執(zhí)行“狀態(tài)管理”)的方法。瀏覽器和 Web 服務(wù)器除了在短暫的實(shí)際信息交換階段以外總是斷開的,而用戶向 Web 服務(wù)器發(fā)送的每個(gè)請(qǐng)求都是單獨(dú)處理的,與其他所有請(qǐng)求無關(guān)。然而在大多數(shù)情況下,都有必要讓 Web 服務(wù)器在您請(qǐng)求某個(gè)頁面時(shí)對(duì)您進(jìn)行識(shí)別。例如,購物站點(diǎn)上的 Web 服務(wù)器跟蹤每個(gè)購物者,以便站點(diǎn)能夠管理購物車和其他的用戶相關(guān)信息。因此 Cookie 的作用就類似于名片,它提供了相關(guān)的標(biāo)識(shí)信息,可以幫助應(yīng)用程序確定如何繼續(xù)執(zhí)行。
使用 Cookie 能夠達(dá)到多種目的,所有這些目的都是為了使 Web 站點(diǎn)記住您。例如,一個(gè)實(shí)施民意測(cè)驗(yàn)的站點(diǎn)可以簡(jiǎn)單地利用 Cookie 作為布爾值,表示您的瀏覽器是否已經(jīng)參與了投票,從而避免您重復(fù)投票; 而那些要求用戶登錄的站點(diǎn)則可以通過 Cookie 來確定您是否已經(jīng)登錄過,這樣您就不必每次都輸入憑據(jù)。
有關(guān) Cookie 的更多背景信息,建議您閱讀 Verizon Web 站點(diǎn)中的“How Internet Cookies Work”一文,地址為 http://www22.verizon.com/about/community/learningcenter/articles/displayarticle1/0,4065,1022z1,00.html(英文)。其作者詳細(xì)解釋了什么是 Cookie 以及 Cookie 是如何在瀏覽器和服務(wù)器之間交換信息的,他還全面總結(jié)了 Cookie 涉及的隱私問題。
順便問一下,您是否想知道它們?yōu)槭裁幢环Q作“Cookie”?Jargon File(又稱為“The New Hacker''s Dictionary”)版本 4.3.3 對(duì)這一術(shù)語的詞源給出了準(zhǔn)確的定義和合理的解釋。您可以在 http://www.catb.org/~esr/jargon/jargon.html#cookie(英文)找到相關(guān)的條目。
在此后的內(nèi)容中,本文將假設(shè)您已經(jīng)知道什么是 Cookie,并且假設(shè)您已經(jīng)清楚為什么要在 ASP.NET 應(yīng)用程序中使用 Cookie。
三、Cookie 的限制
在開始討論 Cookie 的技術(shù)細(xì)節(jié)之前,我想先介紹一下 Cookie 應(yīng)用的幾條限制。大多數(shù)瀏覽器支持最多可達(dá) 4096 字節(jié)的 Cookie,如果要將為數(shù)不多的幾個(gè)值保存到用戶計(jì)算機(jī)上,這一空間已經(jīng)足夠大,但您不能用一個(gè) Cookie 來保存數(shù)據(jù)集或其他大量數(shù)據(jù)。在實(shí)際應(yīng)用中,您可能并不希望在 Cookie 中保存大量的用戶信息,而只希望保存用戶編號(hào)或其他標(biāo)識(shí)符。之后,當(dāng)用戶再次訪問您的站點(diǎn)時(shí),您就可以使用該用戶 ID 在數(shù)據(jù)庫中查找用戶的詳細(xì)信息。(有關(guān)保存用戶信息的說明,請(qǐng)參閱 Cookie 和安全性。)
瀏覽器還限制了您的站點(diǎn)可以在用戶計(jì)算機(jī)上保存的 Cookie 數(shù)。大多數(shù)瀏覽器只允許每個(gè)站點(diǎn)保存 20 個(gè) Cookie。如果試圖保存更多的 Cookie,則最先保存的 Cookie 就會(huì)被刪除。還有些瀏覽器會(huì)對(duì)來自所有站點(diǎn)的 Cookie 總數(shù)作出限制,這個(gè)限制通常為 300 個(gè)。
您最可能遇到的 Cookie 限制是:用戶可以設(shè)置自己的瀏覽器,拒絕接受 Cookie。您很難解決這個(gè)問題,除非完全不使用 Cookie 而是通過其他機(jī)制來保存用戶相關(guān)信息。保存用戶信息的一種常用方法是會(huì)話狀態(tài),但會(huì)話狀態(tài)又依賴于 Cookie。這一點(diǎn)在后面的 Cookie 和會(huì)話狀態(tài)中闡述。
注意:有關(guān)狀態(tài)管理和 Web 應(yīng)用程序中用于保存信息的選項(xiàng)的詳細(xì)信息,請(qǐng)參閱 Introduction to Web Forms State(英文)和 State Management Recommendations(英文)。
更一般的經(jīng)驗(yàn)很可能是,盡管 Cookie 在應(yīng)用程序中非常有用,應(yīng)用程序也不應(yīng)該依賴于能夠保存 Cookie。利用 Cookie 可以做到錦上添花,但不要利用它們來支持關(guān)鍵功能。如果您的應(yīng)用程序必須使用 Cookie,則您可以通過測(cè)試來確定瀏覽器是否接受 Cookie。我在本文后面的檢查瀏覽器是否接受 Cookie 一節(jié)中簡(jiǎn)單介紹了一種測(cè)試方法。
四、編寫 Cookie
您可以利用頁面的 Response(英文)屬性來編寫 Cookie,該屬性提供的對(duì)象使用戶可以將信息添加到由頁面向?yàn)g覽器呈現(xiàn)的信息中。Response 對(duì)象支持一個(gè)名為 Cookies(英文)的集合,您可以向其中添加要寫入瀏覽器的 Cookie。
注意:下面要討論的 Response 對(duì)象和 Request 對(duì)象分別是包含 HttpResponse(英文)和 HttpRequest(英文)類實(shí)例的頁面的屬性。要在文檔中查找 Response 和 Request 的信息,請(qǐng)參閱 HttpResponse 和 HttpRequest 下的內(nèi)容。
在創(chuàng)建 Cookie 時(shí),您需要指定幾個(gè)值。最初,您要指定 Cookie 的名稱和其中保存的值。您可以創(chuàng)建多個(gè) Cookie,每個(gè) Cookie 都必須具有唯一的名稱,以便日后讀取時(shí)識(shí)別。(Cookie 是按名稱保存的,所以如果您創(chuàng)建了兩個(gè)名稱相同的 Cookie,后保存的那一個(gè)將覆蓋前一個(gè)。)
您可能還希望指定 Cookie 的過期日期和時(shí)間。Cookie 一般都寫入到用戶的磁盤,然后可能一直都留在磁盤上。因此,您可以指定 Cookie 過期的日期和時(shí)間。當(dāng)用戶再次訪問您的站點(diǎn)時(shí),瀏覽器會(huì)先檢查您站點(diǎn)的 Cookie 集合,如果某個(gè) Cookie 已經(jīng)過期,瀏覽器不會(huì)把這個(gè) Cookie 隨頁面請(qǐng)求一起發(fā)送給服務(wù)器,而是刪除這個(gè)已經(jīng)過期的 Cookie。(您的站點(diǎn)可能已經(jīng)在用戶計(jì)算機(jī)上寫入了多個(gè) Cookie,每個(gè) Cookie 都有各自的過期日期和時(shí)間。) 請(qǐng)注意,由瀏覽器負(fù)責(zé)管理硬盤上的 Cookie,這將影響您在應(yīng)用程序中對(duì) Cookie 的使用,我很快會(huì)介紹這方面的內(nèi)容。
一個(gè) Cookie 的有效期應(yīng)為多長(zhǎng)?這取決于 Cookie 的用途,換句話說,取決于您的應(yīng)用程序需要 Cookie 值保持有效的時(shí)間有多長(zhǎng)。如果利用 Cookie 統(tǒng)計(jì)網(wǎng)站的訪問者,您可以把有效期設(shè)置為 1 年,如果某個(gè)用戶已有一年時(shí)間未訪問您的站點(diǎn),則可以把該用戶當(dāng)作新的訪問者; 如果利用 Cookie 來保存用戶的首選項(xiàng),則可以把其設(shè)置為永遠(yuǎn)有效(例如 50 年后到期),因?yàn)槎ㄆ谥匦略O(shè)置首選項(xiàng)對(duì)用戶而言是比較麻煩的。有時(shí),您可能需要編寫在數(shù)秒或數(shù)分鐘內(nèi)即過期的 Cookie。在本文后面的檢查瀏覽器是否接受 Cookie 一節(jié)中,我列舉了一個(gè)示例,該示例中創(chuàng)建的 Cookie 的實(shí)際有效期就只有幾秒。
注意:不要忘記用戶隨時(shí)可以刪除自己計(jì)算機(jī)上的 Cookie,所以即使您保存了長(zhǎng)期有效的 Cookie,用戶也可以自行決定將其全部刪除,同時(shí)清除保存在 Cookie 中的所有設(shè)置。
如果沒有設(shè)置 Cookie 的有效期,還是可以創(chuàng)建 Cookie,但它不會(huì)保存到用戶的硬盤上,而是會(huì)成為用戶會(huì)話信息的一部分。如果用戶關(guān)閉瀏覽器或會(huì)話超時(shí),該 Cookie 就會(huì)被刪除。這種非永久性的 Cookie 很適合用來保存只需短時(shí)間保存的信息,或者保存由于安全原因不應(yīng)該寫入客戶計(jì)算機(jī)磁盤的信息。例如,如果用戶使用的是一臺(tái)公用計(jì)算機(jī),而您不希望把 Cookie 寫入這種計(jì)算機(jī)的磁盤上,這時(shí)就可以使用非永久性的 Cookie。
您可以通過多種方法把 Cookie 添加到 Response.Cookies 集合中。以下示例介紹了兩種完成此任務(wù)的方法:
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 集合中添加了兩個(gè) Cookie,一個(gè)稱為“userName”,另一個(gè)稱為“l(fā)astVisit”。對(duì)于第一個(gè) Cookie,我直接設(shè)置了 Response.Cookies 集合的值。您可以使用這種方法向集合中添加值,因?yàn)?Response.Cookies 是從 NameObjectCollectionBase(英文)類型的特殊集合派生得到的。
對(duì)于第二個(gè) Cookie,我創(chuàng)建了 Cookie 對(duì)象的一個(gè)實(shí)例(HttpCookie [英文] 類型),并設(shè)置了其屬性,然后通過 Add 方法把它添加到 Response.Cookies 集合。實(shí)例化 HttpCookie 對(duì)象時(shí),您必須把 Cookie 名稱作為構(gòu)造函數(shù)的一部分進(jìn)行傳遞。
這兩個(gè)示例完成了相同的任務(wù),即向?yàn)g覽器寫入一個(gè) Cookie。您要采用哪種方法主要取決于您的個(gè)人喜好。您可能會(huì)發(fā)現(xiàn)第二種方法在設(shè)置 Cookie 屬性方面要稍微容易一些,但同時(shí)您也會(huì)注意到兩者的差別并不是很大。
在這兩種方法中,有效期值必須為 DateTime 類型。而“l(fā)astVisited”值也是日期/時(shí)間值。但在這種情況下,我必須把日期/時(shí)間值轉(zhuǎn)換為字符串,因?yàn)?Cookie 中的任何值最終都是以字符串的形式保存的。
五、查看您的 Cookie
您可能會(huì)發(fā)現(xiàn),了解創(chuàng)建 Cookie 的效果會(huì)對(duì)您很有幫助。而查看 Cookie 是比較容易的,因?yàn)樗鼈兌际俏谋疚募?#xff0c;關(guān)鍵在于您能找到它們。不同的瀏覽器保存 Cookie 的方式也不同。我將介紹 Internet Explorer 是如何保存 Cookie 的。如果您使用的是其他瀏覽器,請(qǐng)查看該瀏覽器的幫助,以了解有關(guān) Cookie 處理方面的知識(shí)。
查看 Cookie 的一個(gè)簡(jiǎn)便方法是讓 Internet Explorer 為您查找。在 Internet Explorer 中,從“工具”菜單中選擇“Internet 選項(xiàng)”,在“常規(guī)”選項(xiàng)卡中單擊“設(shè)置”,然后單擊“查看文件”。Internet Explorer 將打開一個(gè)窗口,顯示所有的臨時(shí)文件,包括 Cookie。在窗口中查找以“Cookie:”開頭的文件 或查找文本文件。雙擊一個(gè) Cookie,在默認(rèn)的文本文件中打開它。
您也可以在硬盤上查找 Cookie 的文本文件,從而打開 Cookie。Internet Explorer 將站點(diǎn)的 Cookie 保存在文件名格式為 @.txt 的文件中,其中 是您的帳戶名。例如,如果您的名稱為 mikepope,您訪問的站點(diǎn)為 www.contoso.com,那么該站點(diǎn)的 Cookie 將保存在名為 mikepope@www.contoso.txt 的文件中。(該文件名可能包含一個(gè)順序的編號(hào),如 mikepope@www.contoso[1].txt。)
這個(gè) Cookie 文本文件是與用戶相關(guān)的,所以會(huì)按照帳戶分別保存。例如,在 Windows XP 中,您可以在如下所示的目錄中找到 Cookie 文件:
c:\Documents and Settings\\Cookies
要查找最新創(chuàng)建的 Cookie,可以按修改日期對(duì)目錄內(nèi)容進(jìn)行排序,并查找最近修改的文件。
您可以使用文本編輯器打開 Cookie。如果該文件包含多個(gè) Cookie,這些 Cookie 之間將用星號(hào) (*) 分隔。每個(gè) Cookie 的第一行是 Cookie 的名稱,第二行是值,其余各行則包含 Cookie 的日常處理信息,例如過期日期和時(shí)間。Cookie 中還有一個(gè)簡(jiǎn)單的校驗(yàn)和,如果更改 Cookie 名稱或值的長(zhǎng)度,瀏覽器就會(huì)檢測(cè)到修改并刪除該 Cookie。
六、多值 Cookie(子鍵)
以上示例為每個(gè)要保存的值(用戶名、上次訪問時(shí)間)都使用了一個(gè) Cookie 。您也可以在一個(gè) Cookie 中保存多個(gè)名稱/值對(duì)。名稱/值對(duì)也稱作“鍵”或“子鍵”,具體取決于您讀取的內(nèi)容。(如果您熟悉 URL 的結(jié)構(gòu),就會(huì)發(fā)現(xiàn)子鍵與其中的查詢字符串非常相象。) 例如,如果不希望創(chuàng)建名為“userName”和“l(fā)astVisit”的兩個(gè)單獨(dú)的 Cookie,可以創(chuàng)建一個(gè)名為“userInfo”的 Cookie,并使其包含兩個(gè)子鍵:“userName”和“l(fā)astVisit”。
有很多原因會(huì)讓我們用子鍵來代替單獨(dú)的 Cookie。最顯而易見的是,把相關(guān)或類似的信息放在一個(gè) Cookie 中會(huì)比較有條理。另外,由于所有信息都在一個(gè) Cookie 中,所以諸如有效期之類的 Cookie 屬性就適用于所有信息。(當(dāng)然,如果要為不同類型的信息指定不同的過期日期,就應(yīng)該把信息保存在單獨(dú)的 Cookie 中。)
帶有子鍵的 Cookie 還可以幫助您減小 Cookie 的大小。如前面的 Cookie 的限制一節(jié)所述,Cookie 的總大小限制在 4096 字節(jié)以內(nèi),而且不能為一個(gè)網(wǎng)站保存超過 20 個(gè) Cookie。利用帶子鍵的單個(gè) Cookie,站點(diǎn)的 Cookie 數(shù)量就不會(huì)超過 20 個(gè)的限制。此外,一個(gè) Cookie 會(huì)占用大約 50 個(gè)字符的基本空間開銷(用于保存有效期信息等),再加上其中保存的值的長(zhǎng)度,其總和接近 4K 的限制。如果使用五個(gè)子鍵而不是五個(gè)單獨(dú)的 Cookie,您可以省去四個(gè) Cookie 的基本空間開銷,總共能節(jié)省大約 200 個(gè)字節(jié)。
要?jiǎng)?chuàng)建帶子鍵的 Cookie,您可以使用用于編寫單個(gè) Cookie 的各種語法。以下示例顯示了編寫同一 Cookie 的兩種不同方法,其中的每個(gè) Cookie 都帶有兩個(gè)子鍵:
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 有效范圍
默認(rèn)情況下,一個(gè)站點(diǎn)的全部 Cookie 都一起保存在客戶機(jī)上,而且所有這些 Cookie 都會(huì)隨著對(duì)該站點(diǎn)發(fā)送的請(qǐng)求一起發(fā)送到服務(wù)器,也就是說,站點(diǎn)的每個(gè)頁面都能得到該站點(diǎn)的所有 Cookie。但有時(shí)候,您可能希望 Cookie 更具有針對(duì)性,這時(shí),您可以通過兩種方法設(shè)置 Cookie 的有效范圍:
·把 Cookie 的有效范圍限制在服務(wù)器上的一個(gè)文件夾中,實(shí)際上這樣就將 Cookie 限制到站點(diǎn)上的某個(gè)應(yīng)用程序。
·把有效范圍設(shè)置為某個(gè)域,從而允許您指定域中的哪些子域可以訪問 Cookie。
1、將 Cookie 限制到某個(gè)文件夾或應(yīng)用程序
要將 Cookie 限制到服務(wù)器上的某個(gè)文件夾,請(qǐng)按如下方法設(shè)置 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)
當(dāng)然,您也可以通過直接設(shè)置 Response.Cookies 來編寫 Cookie,如前文所述。
路徑可以是站點(diǎn)根目錄下的物理路徑,也可以是虛擬根目錄。這樣一來,Cookie 就只能用于 Application1 文件夾或虛擬根目錄中的頁面。例如,如果您的站點(diǎn)名為 www.contoso.com,則前面示例中生成的 Cookie 就只能用于路徑為 http://www.contoso.com/Application1/ 的頁面以及該文件夾下的所有頁面,而不適用于其他應(yīng)用程序中的頁面,如 http://www.contoso.com/Application2/ 或 http://www.contoso.com/ 下的頁面。
提示:通過對(duì) Internet Explorer 和 Mozilla 瀏覽器進(jìn)行測(cè)試發(fā)現(xiàn),此處使用的路徑是區(qū)分大小寫的。一般而言,Windows 服務(wù)器上的 URL 不區(qū)分大小寫,但這種情況例外。您無法控制用戶如何在瀏覽器中輸入 URL,但是,如果您的應(yīng)用程序依賴于與特定路徑相關(guān)的 Cookie,則請(qǐng)確保您所創(chuàng)建的所有超鏈接中的 URL 與 Path 屬性值的大小寫相匹配。
2、將Cookie 的有效范圍限制到域
默認(rèn)情況下,Cookie 與特定的域相關(guān)聯(lián)。例如,如果您的站點(diǎn)是 www.contoso.com,那么當(dāng)用戶向該站點(diǎn)請(qǐng)求頁面時(shí),您編寫的 Cookie 就被發(fā)送到服務(wù)器。(有特定路徑值的 Cookie 除外,我在上一節(jié)剛剛解釋過。) 如果您的站點(diǎn)有子域(例如 contoso.com、sales.contoso.com 和 support.contoso.com),就可以把 Cookie 同特定的子域相關(guān)聯(lián)。為此,需要設(shè)置 Cookie 的 Domain 屬性,如下所示:
Response.Cookies("domain").Value = DateTime.Now.ToString
Response.Cookies("domain").Expires = DateTime.Now.AddDays(1)
Response.Cookies("domain").Domain = "support.contoso.com"
如果按照這種方式設(shè)置域,則 Cookie 只能用于指定子域中的頁面。
您也可以利用 Domain 屬性來創(chuàng)建可在多個(gè)子域中共享的 Cookie。例如,對(duì)域進(jìn)行如下設(shè)置:
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。
總結(jié)
以上是生活随笔為你收集整理的ASP.NET中Cookie编程的基础知识的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 抽象工厂的应用
- 下一篇: ASP.NET 安全认证(四)