ASP.NET Cookie 概觀
更新:2007 年 11 月
Cookie 是在 Web 伺服器和瀏覽器之間,伴隨要求和網頁傳送的一小段文字。Cookie 包含 Web 應用程式能夠在使用者造訪網站時讀取的資訊。
這個主題包含:
案例
背景
程式碼範例
類別參考
其他資源
新功能
案例
Cookie 提供 Web 應用程式儲存使用者特定資訊的方法。例如,當使用者造訪網站時,您可以使用 Cookie 儲存使用者偏好設定或其他資訊。當使用者下次造訪網站時,應用程式可以擷取之前儲存的資訊。
回到頁首
背景
Cookie 是在 Web 伺服器和瀏覽器之間,伴隨要求和網頁傳送的一小段文字。Cookie 包含 Web 應用程式能夠在使用者造訪網站時讀取的資訊。
例如,如果使用者要求網站的網頁,應用程式除了傳送網頁以外,也會傳送包含日期和時間的 Cookie。當使用者的瀏覽器取得網頁時,瀏覽器也會取得儲存在使用者硬碟資料夾中的 Cookie。
如果使用者稍後再次要求網站的網頁,當使用者輸入 URL 時,瀏覽器會在硬碟中尋找與 URL 關聯的 Cookie。如果 Cookie 存在,瀏覽器會將 Cookie 跟網頁要求一起傳送到您的網站。然後您的應用程式可以判斷使用者上次造訪網站的日期和時間。您可以使用這項資訊對使用者顯示訊息或檢查過期日。
Cookie 是與網站而不是特定網頁有關聯,因此不論使用者從網站要求的網頁為何,瀏覽器和伺服器都會交換 Cookie 資訊。當使用者造訪不同的網站時,每個網站也會將 Cookie 傳送至使用者的瀏覽器。瀏覽器會分開儲存所有的 Cookie。
Cookie 協助網站儲存造訪者的資訊。更明白的說法是,Cookie 是維護 Web 應用程式連續性的一種方法。換句話說,就是執行狀態管理的一種方法。除了實際交換資訊的短暫時間以外,瀏覽器和 Web 伺服器是中斷連接的。使用者對 Web 伺服器做出的每個要求,都會被視為獨立於任何其他要求。然而在許多情況下,如果當使用者要求網頁時,Web 伺服器能夠辨認使用者是很有用的。例如,購物網站的 Web 伺服器會持續追蹤個別購物者,因此網站能夠管理購物車和其他使用者特定資訊。因此 Cookie 的角色就像是一種名片,呈現相關的識別以協助應用程式了解如何繼續。
Cookie 有許多用途,都與協助網站記住使用者相關。例如,舉行投票的網站會簡單地使用布林值的 Cookie 資料,表示使用者的瀏覽器是否已經參加投票,讓使用者無法投票兩次。要求使用者登入的網站會使用 Cookie 記錄使用者已經登入,讓使用者不需要一直輸入認證。
Cookie 限制
大部分瀏覽器支援最多 4096 位元組的 Cookie。因為這項容量大小限制,所以 Cookie 最好用來儲存少量的資料,或最好儲存像是使用者 ID 的識別項。使用者 ID 可以用來識別使用者,然後從資料庫或其他資料存放區讀取使用者資訊 (請參閱以下的「Cookie 和安全性」一節以獲得儲存使用者資訊的安全性隱含資訊)。
瀏覽器也會強制限制在使用者電腦上能夠儲存的網站 Cookie 數量。大部分的瀏覽器只允許每個網站儲存 20 個 Cookie。如果您嘗試儲存更多,就會捨棄最舊的 Cookie。某些瀏覽器也會有接受來自所有網站 Cookie 數量的絕對限制,通常是 300。
您會遇到的 Cookie 限制是使用者能夠設定瀏覽器拒絕 Cookie。如果您定義 P3P 隱私權原則並將其置於網站的根目錄,更多瀏覽器就會接受網站的 Cookie。然而,您應盡可能避免完全依賴 Cookie 所有資訊,而是使用不同的機制儲存使用者特定資訊。儲存使用者資訊的一般方法是工作階段狀態,但是工作階段狀態是依照 Cookie 而定,在稍後的<Cookie 和工作階段狀態>一節中會說明。
注意事項: |
---|
如需狀態管理以及在 Web 應用程序中儲存資訊之選項的詳細資訊,請參閱 ASP.NET 狀態管理概觀和 ASP.NET 狀態管理建議事項。 |
雖然在應用程式中 Cookie 很有用,但是應用程式不應該太過依賴 Cookie 儲存資料。請勿使用 Cookie 支援重要功能。如果應用程式必須依賴 Cookie,您可以測試瀏覽器是否會接受 Cookie。請參閱這個主題稍後的<檢查瀏覽器是否接受 Cookie>一節。
撰寫 Cookie
瀏覽器負責管理使用者系統上的 Cookie。Cookie 是經由公開稱為 Cookies 集合的 HttpResponse 物件傳送至瀏覽器。您可以存取 HttpResponse 物件做為 Page 類別的 Response 屬性。任何想要傳送至瀏覽器的 Cookie 都必須加入這個集合。當建立 Cookie 時,您會指定 Name 和 Value。每個 Cookie 都必須有唯一的名稱,以便稍後從瀏覽器讀取時能夠識別它。因為 Cookie 是使用名稱儲存,所以將兩個 Cookie 命名為相同名稱會導致其中一個被覆寫。
您也可以設定 Cookie 的到期日期和時間。當使用者造訪寫入 Cookie 的網站時,瀏覽器會刪除過期的 Cookie。Cookie 的到期時間應該設定為應用程式將 Cookie 值視為有效的期間。若要讓 Cookie 有效地永遠不過期,可以將到期日設定為從現在開始 50 年後。
注意事項: |
---|
使用者可以隨時清除電腦上的 Cookie。即使使用很長的到期時間儲存 Cookie,但是使用者仍可以決定刪除所有的 Cookie,因而去除 Cookie 中儲存的任何設定。 |
如果不設定 Cookie 的到期日,仍會建立 Cookie 但是不儲存在使用者的硬碟上,而是維護 Cookie 就被當做使用者工作階段資訊的一部分。當使用者關閉瀏覽器時就會捨棄 Cookie。對於只需儲存短暫時間,或是基於安全性因素不應該寫入用戶端電腦磁碟的資訊來說,像這種非持續性的 Cookie 就很有用。例如,如果使用者使用不想將 Cookie 寫入磁碟的公用電腦,非持續性的 Cookie 就很有用。
您可以使用幾種方式將 Cookie 加入 Cookies 集合。下列範例顯示寫入 Cookie 的兩種方法:
Response.Cookies("userName").Value = "patrick"
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)
Response.Cookies["userName"].Value = "patrick";
Response.Cookies["userName"].Expires = DateTime.Now.AddDays(1);
HttpCookie aCookie = new HttpCookie("lastVisit");
aCookie.Value = DateTime.Now.ToString();
aCookie.Expires = DateTime.Now.AddDays(1);
Response.Cookies.Add(aCookie);
這個範例將兩個 Cookie 加入 Cookies 集合,一個名為 userName 而另一個名為 lastVisit。針對第一個 Cookie,會直接設定 Cookies 集合的值。因為 Cookies 衍生自 NameObjectCollectionBase 型別的特殊集合,所以您可以使用這個方式將值加入集合。
針對第二個 Cookie,程式碼會建立 HttpCookie 型別的物件執行個體、設定其屬性,然後經由 Add 方法將其加入 Cookies 集合。當您個體化 HttpCookie 物件時,您必須傳遞 Cookie 名稱做為建構函式的一部分。
兩個範例都完成相同的工作,將 Cookie 寫入瀏覽器。在這兩個方法中的到期值都必須是 DateTime 型別。然而,lastVisited 值也是日期時間值。因為所有 Cookie 值都是以字串形式儲存,所以日期時間值必須轉換為 String。
使用一個值以上的 Cookie
您可以在 Cookie 中儲存一個值,例如使用者名稱和上次造訪時間。您也可以在單一 Cookie 中儲存多個名稱/值組。名稱/值組會參考為子索引鍵 (子索引鍵配置方式很像 URL 中的查詢字串)。例如,您可以建立擁有 userName 和 lastVisit 子索引鍵,名為 userInfo 的單一 Cookie,而不是建立兩個名為 userName 和 lastVisit 的不同 Cookie。
您可能會基於幾種理由使用子索引鍵。首先,將相關或類似資訊放入單一 Cookie 很方便。此外,因為所有資訊都在單一 Cookie 中,所以像是到期日的 Cookie 屬性會套用至所有資訊 (相反地,如果您想要指派不同的到期日給不同類型的資訊,就應該將資訊儲存在不同的 Cookie 中)。
使用子索引鍵的 Cookie 也可以協助您限制 Cookie 檔案的大小。如同稍早在<Cookie 限制>一節中的注意事項提過,Cookie 通常都限制在 4096 個位元組,並且每個網站無法儲存超過 20 個 Cookie。您可以藉由搭配子索引鍵的單一 Cookie,在每個網站只配置 20 個 Cookie 的限制下,可以耗用較少的數量。此外,單一 Cookie 會使用 50 字元處理預先配置 (到期資訊等),加上儲存在其中的值長度,這全部計算在 4096 位元組的限制中。如果您儲存五個子索引鍵而不是五個不同的 Cookie,就可以節省不同 Cookie 的預先配置,大約在 200 個位元組。
若要使用子索引鍵建立 Cookie,您可以使用各種不同的語法撰寫單一 Cookie。下列範例顯示撰寫相同 Cookie 的兩種方法,每種方法使用兩個子索引鍵:
Response.Cookies("userInfo")("userName") = "patrick"
Response.Cookies("userInfo")("lastVisit") = DateTime.Now.ToString()
Response.Cookies("userInfo").Expires = DateTime.Now.AddDays(1)
Dim aCookie As New HttpCookie("userInfo")
aCookie.Values("userName") = "patrick"
aCookie.Values("lastVisit") = DateTime.Now.ToString()
aCookie.Expires = DateTime.Now.AddDays(1)
Response.Cookies.Add(aCookie)
Response.Cookies["userInfo"]["userName"] = "patrick";
Response.Cookies["userInfo"]["lastVisit"] = DateTime.Now.ToString();
Response.Cookies["userInfo"].Expires = DateTime.Now.AddDays(1);
HttpCookie aCookie = new HttpCookie("userInfo");
aCookie.Values["userName"] = "patrick";
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 的 Path 屬性,如同下列範例所示:
Dim appCookie As New HttpCookie("AppCookie")
appCookie.Value = "written " & DateTime.Now.ToString()
appCookie.Expires = DateTime.Now.AddDays(1)
appCookie.Path = "/Application1"
Response.Cookies.Add(appCookie)
HttpCookie appCookie = new HttpCookie("AppCookie");
appCookie.Value = "written " + DateTime.Now.ToString();
appCookie.Expires = DateTime.Now.AddDays(1);
appCookie.Path = "/Application1";
Response.Cookies.Add(appCookie);
注意事項: |
---|
您也可以如同先前範例中所示,將 Cookie 直接加入 Cookies 集合以撰寫 Cookie。 |
路徑可以是網站根目錄或是虛擬根目錄下的實體路徑。這個效果是只有 Application1 資料夾或虛擬根目錄下的網頁才能使用 Cookie。例如,如果您的網站叫做 www.contoso.com,只有使用 https://www.contoso.com/Application1/ 網頁和該資料夾下的任何網頁,才能使用先前範例中所建立的 Cookie。然而,其他應用程式中的網頁像是 https://www.contoso.com/Application2/ 或 https://www.contoso.com/ 就無法使用這個 Cookie。
注意事項: |
---|
在某些瀏覽器中的路徑會區分大小寫。您無法控制使用者如何在瀏覽器中輸入 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"
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"
Response.Cookies["domain"].Value = DateTime.Now.ToString();
Response.Cookies["domain"].Expires = DateTime.Now.AddDays(1);
Response.Cookies["domain"].Domain = "contoso.com";
然後主網域以及 sales.contoso.com 和 support.contoso.com 網域就可以使用 Cookie。
讀取 Cookie
當瀏覽器對伺服器提出要求時,就會將 Cookie 和要求一起傳送至伺服器。在 ASP.NET 應用程式中,您可以使用 HttpRequest 物件讀取 Cookie,其當做 Page 類別的 Request 屬性使用。HttpRequest 物件的結構在本質上與 HttpResponse 物件相同,所以您可以使用將 Cookie 寫入 HttpResponse 物件的相同方式,從 HttpRequest 物件讀取 Cookie。下列程式碼範例會示範從名為 username 的 Cookie 取得值的兩種方式,並將其值顯示在 Label 控制項中:
If Not Request.Cookies("userName") Is Nothing Then
Label1.Text = Server.HtmlEncode(Request.Cookies("userName").Value)
End If
If Not Request.Cookies("userName") Is Nothing Then
Dim aCookie As HttpCookie = Request.Cookies("userName")
Label1.Text = Server.HtmlEncode(aCookie.Value)
End If
if(Request.Cookies["userName"] != null)
Label1.Text = Server.HtmlEncode(Request.Cookies["userName"].Value);
if(Request.Cookies["userName"] != null)
{
HttpCookie aCookie = Request.Cookies["userName"];
Label1.Text = Server.HtmlEncode(aCookie.Value);
}
在嘗試取得 Cookie 值之前,您應該確認 Cookie 是否存在。如果 Cookie 不存在,就會發生 NullReferenceException 例外狀況。請注意,在網頁上顯示 Cookie 之前,也會呼叫 HtmlEncode 方法編碼 Cookie 的內容。這是為了確定惡意使用者並未將可執行的指令碼加入 Cookie 中。如需 Cookie 安全性的詳細資訊,請參閱<Cookie 和安全性>一節。
注意事項: |
---|
因為不同的瀏覽器會使用不同的方式儲存 Cookie,所以相同電腦上的不同瀏覽器不一定要能夠讀取對方的 Cookie。例如,如果使用 Internet Explorer 測試一次網頁,但是稍後使用不同的瀏覽器再次測試,則第二個瀏覽器找不到 Internet Explorer 儲存的 Cookie。 |
讀取 Cookie 中子索引鍵的值與設定它的方法類似。下列程式碼範例會示範取得子索引鍵值的一種方式:
If Not Request.Cookies("userInfo") Is Nothing Then
Label1.Text = _
Server.HtmlEncode(Request.Cookies("userInfo")("userName"))
Label2.Text = _
Server.HtmlEncode(Request.Cookies("userInfo")("lastVisit"))
End If
if(Request.Cookies["userInfo"] != null)
{
Label1.Text =
Server.HtmlEncode(Request.Cookies["userInfo"]["userName"]);
Label2.Text =
Server.HtmlEncode(Request.Cookies["userInfo"]["lastVisit"]);
}
在之前的範例中,程式碼會讀取子索引鍵 lastVisit 的值,其在稍早被設定為 DateTime 值的字串表示。Cookie 會以字串形式儲存值,因此如果您想要使用 lastVisit 值做為日期,必須將其轉換為適當的類型,如同下列範例所示:
Dim dt As DateTime
dt = DateTime.Parse(Request.Cookies("userInfo")("lastVisit"))
DateTime dt;
dt = DateTime.Parse(Request.Cookies["userInfo"]["lastVisit"]);
Cookie 中的子索引鍵會以 NameValueCollection 型別的集合形式輸入。因此,另一個取得個別子索引鍵的方式,是取得子索引鍵集合然後根據名稱擷取子索引鍵的值,如同下列範例所示:
If Not Request.Cookies("userInfo") Is Nothing Then
Dim UserInfoCookieCollection As _
System.Collections.Specialized.NameValueCollection
UserInfoCookieCollection = Request.Cookies("userInfo").Values
Label1.Text = _
Server.HtmlEncode(UserInfoCookieCollection("userName"))
Label2.Text = _
Server.HtmlEncode(UserInfoCookieCollection("lastVisit"))
End If
if(Request.Cookies["userInfo"] != null)
{
System.Collections.Specialized.NameValueCollection
UserInfoCookieCollection;
UserInfoCookieCollection = Request.Cookies["userInfo"].Values;
Label1.Text =
Server.HtmlEncode(UserInfoCookieCollection["userName"]);
Label2.Text =
Server.HtmlEncode(UserInfoCookieCollection["lastVisit"]);
}
變更 Cookie 的到期日
瀏覽器負責管理 Cookie,而 Cookie 的到期時間和日期可以協助瀏覽器管理 Cookie 的儲存。因此,雖然您可以讀取 Cookie 的名稱和值,但是無法讀取 Cookie 的到期日期和時間。當瀏覽器將 Cookie 資訊傳送至伺服器時,瀏覽器並不會包含到期資訊 (Cookie 的 Expires 屬性永遠會傳回為零的日期時間值)。如果您擔心 Cookie 的到期日,就必須重設它,這項動作在<修改和刪除 Cookie>一節中有說明。
注意事項: |
---|
在將 Cookie 傳送至瀏覽器之前,您可以讀取在 HttpResponse 物件中設定的 Cookie Expires 屬性。然而,您無法從 HttpRequest 物件取回到期資訊。 |
讀取 Cookie 集合
您可能會偶爾需要讀取網頁能夠使用的所有 Cookie。若要讀取網頁能夠使用的所有 Cookie 名稱和值,您可以使用像是下列的程式碼在 Cookies 集合上執行迴圈。
Dim i As Integer
Dim output As System.Text.StringBuilder = New System.Text.StringBuilder
Dim aCookie As HttpCookie
For i = 0 to Request.Cookies.Count - 1
aCookie = Request.Cookies(i)
output.Append("Cookie name = " & Server.HtmlEncode(aCookie.Name) _
& "<br />")
output.Append("Cookie value = " & _
Server.HtmlEncode(aCookie.Value) & "<br /><br />")
Next
Label1.Text = output.ToString()
System.Text.StringBuilder output = new System.Text.StringBuilder();
HttpCookie aCookie;
for(int i=0; i<Request.Cookies.Count; i++)
{
aCookie = Request.Cookies[i];
output.Append("Cookie name = " + Server.HtmlEncode(aCookie.Name)
+ "<br />");
output.Append("Cookie value = " + Server.HtmlEncode(aCookie.Value)
+ "<br /><br />");
}
Label1.Text = output.ToString();
注意事項: |
---|
當您執行這個程式碼時,可能會看到名為 ASP.NET_SessionId 的 Cookie。這是 ASP.NET 用來儲存工作階段唯一識別項的 Cookie。工作階段 Cookie 並不會保存在您的硬碟上。如需工作階段 Cookie 的詳細資訊,請參閱這個主題稍後的<Cookie 和工作階段狀態>一節。 |
之前範例的限制是如果 Cookie 有子索引鍵,就會將子索引鍵顯示為單一名稱/值字串。您可以讀取 Cookie 的 HasKeys 屬性判斷 Cookie 是否有子索引鍵。如果有的話,您可以讀取子索引鍵集合以取得個別子索引鍵的名稱和值。您可以藉由索引值,直接從 Values 集合讀取子索引鍵值。在 Values 集合的 AllKeys 成員中可以取得對應的子索引鍵名稱,其會傳回字串陣列。您也可以使用 Values 集合的 Keys 成員。然而,當第一次存取 AllKeys 屬性時會將其快取。相反地,當每次存取 Keys 屬性時會建置一個陣列。因此,在相同網頁要求內容中的後續存取,AllKeys 屬性會比較快。
下列範例顯示對之前範例做出的修改。其使用 HasKeys 屬性測試子索引鍵,如果偵測到子索引鍵,範例就會從 Values 集合取得子索引鍵:
Dim i As Integer
Dim j As Integer
Dim output As System.Text.StringBuilder = New StringBuilder()
Dim aCookie As HttpCookie
Dim subkeyName As String
Dim subkeyValue As String
For i = 0 To Request.Cookies.Count - 1
aCookie = Request.Cookies(i)
output.Append("Name = " & aCookie.Name & "<br />")
If aCookie.HasKeys Then
For j = 0 To aCookie.Values.Count - 1
subkeyName = Server.HtmlEncode(aCookie.Values.AllKeys(j))
subkeyValue = Server.HtmlEncode(aCookie.Values(j))
output.Append("Subkey name = " & subkeyName & "<br />")
output.Append("Subkey value = " & subkeyValue & _
"<br /><br />")
Next
Else
output.Append("Value = " & Server.HtmlEncode(aCookie.Value) & _
"<br /><br />")
End If
Next
Label1.Text = output.ToString()
for(int i=0; i<Request.Cookies.Count; i++)
{
aCookie = Request.Cookies[i];
output.Append("Name = " + aCookie.Name + "<br />");
if(aCookie.HasKeys)
{
for(int j=0; j<aCookie.Values.Count; j++)
{
subkeyName = Server.HtmlEncode(aCookie.Values.AllKeys[j]);
subkeyValue = Server.HtmlEncode(aCookie.Values[j]);
output.Append("Subkey name = " + subkeyName + "<br />");
output.Append("Subkey value = " + subkeyValue +
"<br /><br />");
}
}
else
{
output.Append("Value = " + Server.HtmlEncode(aCookie.Value) +
"<br /><br />");
}
}
Label1.Text = output.ToString();
此外,您可以如同下列範例所示,擷取子索引鍵做為 NameValueCollection 物件:
Dim i As Integer
Dim j As Integer
Dim output As System.Text.StringBuilder = New StringBuilder()
Dim aCookie As HttpCookie
Dim subkeyName As String
Dim subkeyValue As String
For i = 0 To Request.Cookies.Count - 1
aCookie = Request.Cookies(i)
output.Append("Name = " & aCookie.Name & "<br />")
If aCookie.HasKeys Then
Dim CookieValues As _
System.Collections.Specialized.NameValueCollection = _
aCookie.Values
Dim CookieValueNames() As String = CookieValues.AllKeys
For j = 0 To CookieValues.Count - 1
subkeyName = Server.HtmlEncode(CookieValueNames(j))
subkeyValue = Server.HtmlEncode(CookieValues(j))
output.Append("Subkey name = " & subkeyName & "<br />")
output.Append("Subkey value = " & subkeyValue & _
"<br /><br />")
Next
Else
output.Append("Value = " & Server.HtmlEncode(aCookie.Value) & _
"<br /><br />")
End If
Next
Label1.Text = output.ToString
System.Text.StringBuilder output = new System.Text.StringBuilder();
HttpCookie aCookie;
string subkeyName;
string subkeyValue;
for (int i = 0; i < Request.Cookies.Count; i++)
{
aCookie = Request.Cookies[i];
output.Append("Name = " + aCookie.Name + "<br />");
if (aCookie.HasKeys)
{
System.Collections.Specialized.NameValueCollection CookieValues =
aCookie.Values;
string[] CookieValueNames = CookieValues.AllKeys;
for (int j = 0; j < CookieValues.Count; j++)
{
subkeyName = Server.HtmlEncode(CookieValueNames[j]);
subkeyValue = Server.HtmlEncode(CookieValues[j]);
output.Append("Subkey name = " + subkeyName + "<br />");
output.Append("Subkey value = " + subkeyValue +
"<br /><br />");
}
}
else
{
output.Append("Value = " + Server.HtmlEncode(aCookie.Value) +
"<br /><br />");
}
}
Label1.Text = output.ToString();
修改和刪除 Cookie
您無法直接修改 Cookie。而是使用新的值建立新 Cookie,然後將 Cookie 傳送至瀏覽器以覆寫用戶端上的舊版 Cookie 來進行變更。下列程式碼範例會示範如何變更儲存使用者造訪網站次數的 Cookie 值:
Dim counter As Integer
If Request.Cookies("counter") Is Nothing Then
counter = 0
Else
counter = Int32.Parse(Request.Cookies("counter").Value)
End If
counter += 1
Response.Cookies("counter").Value = counter.ToString
Response.Cookies("counter").Expires = DateTime.Now.AddDays(1)
int counter;
if (Request.Cookies["counter"] == null)
counter = 0;
else
{
counter = int.Parse(Request.Cookies["counter"].Value);
}
counter++;
Response.Cookies["counter"].Value = counter.ToString();
Response.Cookies["counter"].Expires = DateTime.Now.AddDays(1);
刪除 Cookie
刪除 Cookie (從使用者的硬碟上實際移除它) 是加以修改的變化方式。因為 Cookie 在使用者的電腦上,所以您無法直接移除 Cookie。然而,可以讓瀏覽器替您刪除 Cookie。這個技巧是使用與想要刪除之 Cookie 的相同名稱建立新 Cookie,但是將 Cookie 的到期日設定為今天以前。當瀏覽器檢查 Cookie 的到期日時,瀏覽器會捨棄當時過期的 Cookie。下列程式碼範例會示範刪除應用程式所有可用 Cookie 的一種方法:
Dim aCookie As HttpCookie
Dim i As Integer
Dim cookieName As String
Dim limit As Integer = Request.Cookies.Count - 1
For i = 0 To limit
cookieName = Request.Cookies(i).Name
aCookie = New HttpCookie(cookieName)
aCookie.Expires = DateTime.Now.AddDays(-1)
Response.Cookies.Add(aCookie)
Next
HttpCookie aCookie;
string cookieName;
int limit = Request.Cookies.Count;
for (int i=0; i<limit; i++)
{
cookieName = Request.Cookies[i].Name;
aCookie = new HttpCookie(cookieName);
aCookie.Expires = DateTime.Now.AddDays(-1);
Response.Cookies.Add(aCookie);
}
修改或刪除子索引鍵
修改個別子索引鍵與建立方式相同,如同下列範例所示:
Response.Cookies("userInfo")("lastVisit") = DateTime.Now.ToString()
Response.Cookies("userInfo").Expires = DateTime.Now.AddDays(1)
Response.Cookies["userInfo"]["lastVisit"] = DateTime.Now.ToString();
Response.Cookies["userInfo"].Expires = DateTime.Now.AddDays(1);
若要刪除個別子索引鍵,可以管理包含子索引鍵的 Values Cookie 集合。首先從 Cookies 物件取得 Cookie 以便重新建立。然後呼叫 Values 集合的 Remove 方法,將要刪除的子索引鍵名稱傳遞至 Remove 方法。然後將 Cookie 加入 Cookies 集合,就會使用修改過的格式將它傳回瀏覽器。下列程式碼範例會示範如何刪除子索引鍵。在範例中,要移除的子索引鍵名稱會指定在變數中。
Dim subkeyName As String
subkeyName = "userName"
Dim aCookie As HttpCookie = Request.Cookies("userInfo")
aCookie.Values.Remove(subkeyName)
aCookie.Expires = DateTime.Now.AddDays(1)
Response.Cookies.Add(aCookie)
string subkeyName;
subkeyName = "userName";
HttpCookie aCookie = Request.Cookies["userInfo"];
aCookie.Values.Remove(subkeyName);
aCookie.Expires = DateTime.Now.AddDays(1);
Response.Cookies.Add(aCookie);
Cookie 和安全性
擁有 Cookie 的安全性風險類似於從用戶端取得資料。在應用程式中,Cookie 是另一種使用者輸入形式,因此牽涉了檢查與欺騙。因為在使用者自己的電腦上可以使用 Cookie,所以使用者至少可以看到儲存在 Cookie 中的資料。使用者也可以在瀏覽器將 Cookie 傳送給您之前變更它。
絕對不要在 Cookie 中儲存敏感資料,例如使用者姓名、密碼、信用卡號碼等。請勿在 Cookie 中放置不應該交到使用者手中的任何資料,或是交給可能會竊取 Cookie 的人。
同樣地,對從 Cookie 中取得的資訊抱持懷疑態度。請不要假設這項資料與您寫入時的相同。請使用與處理使用者輸入 Web 網頁資料的相同保護措施來處理 Cookie 值。這個主題之前的範例顯示,在網頁中顯示值之前會先以 HTML 方式編碼 Cookie 的內容,如同顯示從使用者取得的任何資訊之前會進行的動作。
Cookie 會以純文字形式在瀏覽器和伺服器之間傳送,能夠攔截 Web 流量的任何人都可以讀取 Cookie。您可以將 Cookie 的屬性設定為只有在連接使用 Secure Sockets Layer (SSL) 時才傳輸 Cookie。當 Cookie 在使用者電腦上時,SSL 不會保護 Cookie 不讓使用者讀取或管理,但是因為 Cookie 經過加密,所以在傳輸過程中會保護 Cookie 不讓別人讀取。如需詳細資訊,請參閱 Web 應用程式的基本安全性實行方式。
判斷瀏覽器是否接受 Cookie
使用者可以將瀏覽器設定為拒絕 Cookie。如果無法寫入 Cookie 並不會引發任何錯誤。同樣地,瀏覽器也不會將目前 Cookie 設定的任何資訊傳送至伺服器。
注意事項: |
---|
Cookies 屬性並不表示是否啟用 Cookie。只表示目前的瀏覽器原本是否支援 Cookie。 |
判斷是否接受 Cookie 的一種方法,是嘗試寫入 Cookie 然後再次嘗試讀取 Cookie。如果您無法讀取所寫入的 Cookie,就當做瀏覽器中已關閉 Cookie。
下列程式碼範例會示範如何測試是否接受 Cookie。這個範例是由兩個網頁所構成。第一個網頁會寫入 Cookie,然後將瀏覽器重新導向至第二個網頁。第二個網頁會嘗試讀取 Cookie。然後會將瀏覽器重新導向回第一個網頁,並將使用測試結果的查詢字串變數加入 URL。
第一個網頁的程式碼看起來如下所示:
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
If Request.QueryString("AcceptsCookies") Is Nothing Then
Response.Cookies("TestCookie").Value = "ok"
Response.Cookies("TestCookie").Expires = _
DateTime.Now.AddMinutes(1)
Response.Redirect("TestForCookies.aspx?redirect=" & _
Server.UrlEncode(Request.Url.ToString))
Else
Label1.Text = "Accept cookies = " & _
Server.UrlEncode(Request.QueryString("AcceptsCookies"))
End If
End If
End Sub
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
if (Request.QueryString["AcceptsCookies"] == null)
{
Response.Cookies["TestCookie"].Value = "ok";
Response.Cookies["TestCookie"].Expires =
DateTime.Now.AddMinutes(1);
Response.Redirect("TestForCookies.aspx?redirect=" +
Server.UrlEncode(Request.Url.ToString()));
}
else
{
Label1.Text = "Accept cookies = " +
Server.UrlEncode(
Request.QueryString["AcceptsCookies"]);
}
}
}
網頁會先測試這是否為回傳 (Postback)。如果不是,網頁就會尋找名稱為 AcceptsCookies 的查詢字串變數,以決定是否包含測試結果。如果沒有查詢字串變數,測試就尚未完成,因此程式碼會寫出名為 TestCookie 的 Cookie。在寫出 Cookie 後,範例會呼叫 Redirect 以傳輸至測試網頁 TestForCookies.aspx。附加至測試網頁 URL 的是名為 redirect,包含目前網頁 URL 的查詢字串變數。這可以讓您在執行測試後重新導向回這個網頁。
測試網頁可能都是由程式碼組成,並不需要包含控制項。下列程式碼範例說明測試網頁。
Sub Page_Load()
Dim redirect As String = Request.QueryString("redirect")
Dim acceptsCookies As String
If Request.Cookies("TestCookie") Is Nothing Then
acceptsCookies = "no"
Else
acceptsCookies = "yes"
' Delete test cookie.
Response.Cookies("TestCookie").Expires = _
DateTime.Now.AddDays(-1)
End If
Response.Redirect(redirect & "?AcceptsCookies=" & acceptsCookies, _
True)
End Sub
protected void Page_Load(object sender, EventArgs e)
{
string redirect = Request.QueryString["redirect"];
string acceptsCookies;
if(Request.Cookies["TestCookie"] ==null)
acceptsCookies = "no";
else
{
acceptsCookies = "yes";
// Delete test cookie.
Response.Cookies["TestCookie"].Expires =
DateTime.Now.AddDays(-1);
}
Response.Redirect(redirect + "?AcceptsCookies=" + acceptsCookies,
true);
}
在讀取重新導向查詢字串變數後,程式碼會嘗試讀取 Cookie。如果 Cookie 存在的話,就會基於環境維護因素立即刪除它。當測試完成時,程式碼會根據 redirect 查詢字串變數中傳遞給它的 URL 建構新 URL。新的 URL 也會包括其中包含測試結果的查詢字串變數。最終步驟是使用新的 URL 將瀏覽器重新導向至原始網頁。
在範例中的改進,是將 Cookie 測試結果置於持續性的存放區中 (例如資料庫),因此不需要在使用者每次檢視原始網頁時都重複測試 (根據預設,將測試結果儲存在工作階段狀態中需要 Cookie)。
Cookie 和工作階段狀態
當使用者巡覽至網站時,伺服器會為該使用者建立唯一的工作階段,並且在使用者造訪期間維持這個工作階段。ASP.NET 會為每個工作階段維護工作階段狀態資訊,應用程式可以在其中儲存使用者特定資訊。如需詳細資訊,請參閱ASP.NET 工作階段狀態概觀主題。
ASP.NET 必須追蹤每個使用者的工作階段 ID,以便將使用者對應到伺服器上的工作階段狀態資訊。根據預設,ASP.NET 會使用非持續性的 Cookie 儲存工作階段狀態。然而,如果使用者停用了瀏覽器上的 Cookie,便無法將工作階段狀態資訊存放在 Cookie 中。
ASP.NET 提供格式為 Cookieless 工作階段的替代方案。您可以設定應用程式將工作階段 ID 儲存在網站網頁的 URL 中,而不是儲存在 Cookie 中。如果應用程式依賴工作階段狀態,您可以考慮將其設定為使用 Cookieless 工作階段。然而,在某些受限制的情況下,如果使用者與某人共用 URL (可能是在使用者工作階段仍在使用中時,將 URL 傳送給同事),在使用者共用相同工作階段的情況下,將可能發生無法預期結果。如需設定應用程式使用 Cookieless 工作階段的詳細資訊,請參閱 ASP.NET 狀態管理概觀主題。
回到頁首
程式碼範例
快速入門
管理應用程式狀態 (英文)
使用說明和逐步解說主題
HOW TO:自訂來自 WCF 驗證服務的驗證 Cookie
回到頁首
類別參考
提供型別安全 (Type-Safe) 方式來建立並操作個別 HTTP Cookie。 |
|
取得回應 Cookie 集合。 |
|
取得用戶端送出的 Cookie 的集合。 |
回到頁首
其他資源
回到頁首
新功能
回到頁首
請參閱
概念
參考
回到頁首