天天看點

關于Cookie的知識的總結

會話cookie是一種臨時cookie,它記錄了使用者通路站點時的設定和偏好,當使用者退出浏覽器時,會話cookie就會被删除。

持久cookie的生存時間更長一些,它存儲在使用者的硬碟上,浏覽器退出或計算機重新開機時他們仍然存在。

會話cookie與持久cookie之間的唯一差別就是它們的過期時間。

如果設定了Discard參數(cookie版本1中的參數),或者沒有設定Expires或者Max-Age參數(cookie版本1中的參數)來說明擴充的過期時間,這個cookie就是一個會話cookie。

Cookie可以通過伺服器進行設定,相當于伺服器給使用者貼的一個标簽,用于跟蹤使用者的狀态。

通過伺服器設定的cookie資訊通過響應頭傳回給浏覽器,浏覽器将響應頭中的cookie資訊儲存在本地,當下次向伺服器發送HTTP請求時,就自動将儲存的這些cookie資訊添加到請求頭中(包含通過document.cookie接口設定的cookie)。

下面是退出部落格園登入時的響應頭和請求頭,響應頭中有Set-Cookie字段,請求頭中有Cookie字段:

關于Cookie的知識的總結

通過BOM提供的document.cookie接口,在前端可以對cookie進行操作(增、删、改),本質上是對符合一定規律的一個字元串進行操作,這樣開發人員就可以利用cookie在本地存儲一些資料。當然,建議存儲一些非敏感資訊。

Cookie的限制主要有兩條:

通路cookie時的同源限制

Cookie的個數和尺寸限制

同源限制

Cookie在性質上是綁定在特定的域名下的。當建立了一個cookie後,再給建立它的域名發送請求時,請求頭中都會包含這個cookie。這個限制確定了儲存在cookie中的資訊隻能讓準許的域通路,而無法被其他域通路。

個數和尺寸限制

每個域名下可綁定的cookie的個數是有限的,不同浏覽器所限制的個數不同。

浏覽器對同域名下cookie個數的限制見下表:

浏覽器

可綁定的cookie的個數

IE6

20

IE7

50

Firefox

Opera

30

Safari

沒有硬性限制

Chrome

當超過單個域名限制之後還要再設定cookie,浏覽器就會清除以前設定的cookie。

浏覽器中對于單個cookie的尺寸也有限制,一般限制在4MB。尺寸限制影響到一個域名下的所有cookie,而并非每個cookie單獨限制。

名稱和值 name = value:必填。name和value都是字元序列,除非包含在雙引号内,否則不包括分号、逗号、等号和空格。Web伺服器可以建立任意的name=value關聯,浏覽器在後繼對站點的通路中會将其送會給web伺服器。

域  domain:可選。表示該cookie對于哪個域是有效的。所有向該域發送的請求中都會包含這個cookie資訊。這個值可以包含子域(如www.wrox.com,表示該cookie資訊隻向該域名發送),也可以不包含(如.wrox.com,則對于wrox.com的所有子域都有效)。如果沒有明确規定,那麼這個域會被認作來自設定該cookie的那個伺服器所在的域。

路徑  path:可選。通過這個字段可以為伺服器上特定的文檔配置設定cookie。如果path字段是一個URL路徑字首,就可以附加一個cookie。例如:路徑 /foo與 /foobar和 /foo/bar.html相比對。路徑 / 與域名中的所有内容都比對。預設值是設定 Cookie 時的目前目錄。

失效時間  expires(新版的cookie規範中是max-age字段):可選。這個字段會指定一個日期字元串,用來定義cookie的實際生存期。一旦到了這個日期,就不再存儲或釋出這個cookie了,該cookie就會被删除。如果設定的日期是以前的時間,則cookie會被立刻删除。

日期格式為GMT格式:Wdy, DD-Mon-YYYY HH:MM:SS GMT。

安全标志  secure:可選。該字段不是鍵值對的形式,如果要指定該字段,隻要在設定cookie時添加secure字元即可。設定了該字段後,該cookie隻有在使用SSL連接配接的時候才發送到伺服器。例如:指定域為www.wrox.com的cookie,在制定了secure字段後,該cookie隻能發送給https://www.wrox.com,而發送給http://www.wrox.com的請求不會添加該cookie。

HTTP專用  HttpOnly:可選。該字段隻能在服務端設定,表示該cookie是否能通過JS(BOM的document.cookie接口)去通路。預設情況下HttpOnly字段為空,表示可以通過JS通路該cookie。

按照規範,開發人員無法利用JS在前端修改cookie的HttpOnly字段,不過有的浏覽器沒有這個限制,具體看這篇文章:浏覽器中因cookie設定HttpOnly标志引起的安全問題

關于如何在服務端設定該字段,請看這篇文章:關于Cookie安全性設定的那些事

注意:域、路徑、失效時間、安全标志(secure)和HttpOnly字段都是伺服器給浏覽器的訓示,告訴浏覽器如何存儲和發送cookie,這些參數并不會作為發送到伺服器的cookie資訊的一部分,隻有cookie中的名值對兒(name=value)才會被發送。

在前面的圖檔中,響應頭中的一個Set-Cookie就代表一個cookie;請求頭中的Cookie字段中可以包含多個cookie的名值對兒,而不是僅包含一個cookie的名值對兒。

當用來擷取cookie時,document.cookie傳回目前頁面可用的所有cookie的字元串,一系列由分号隔開的名值對兒。

例如,我在Chrome中打開這個頁面:https://segmentfault.com/a/1190000004556040,在控制台中輸入以下代碼:

控制台中會輸出以下結果:

有七個由分号分隔得名值對兒,表示有七個cookie可用(所有名字和值都是經過URL編碼的,是以必須使用decodeURIComponent()來解碼。)。

點選開發者工具中的Application選項,在左邊找到Cookies下拉菜單,點選第一個域名,就可以看到這七個cookie的詳細資訊。具體如下:

關于Cookie的知識的總結

當用于設定cookie時,document.cookie可以設定一個新的cookie字元串,這個cookie字元串會被解釋并添加到目前現有的cookie集合中。其中名值對兒(name=value)是必須的(最好用encodeURIComponent()對name和value進行編碼),其它字段在cookie的組成部分已做過介紹。

通過document.cookie設定的cookie并不會覆寫現有的cookie,除非設定的cookie的name在現有cookie集合中已經存在,并且path/domain/secure這幾個選項一定要和舊cookie 保持一樣。否則不會修改舊cookie,而是添加了一個新的 cookie。

例子(使用wamp環境):

PHP代碼:

HTML代碼:

JS代碼:

 第一次打開該頁面時,點選顯示cookie按鈕,控制台無輸出内容,谷歌開發者工具中Application頁籤中的cookie選項中也為空。

點選發送請求按鈕,在Network頁籤中檢視頭部資訊:

關于Cookie的知識的總結

在Application頁籤中的cookies選項檢視cookie:

關于Cookie的知識的總結

 現在點選顯示cookie按鈕:

關于Cookie的知識的總結

隻顯示出了名值對兒,沒有顯示該cookie的其它字段的資訊。

接下來點選設定cookie按鈕,重設該cookie,然後再點選顯示cookie按鈕:

關于Cookie的知識的總結

該cookie的值被重設為了ok。

我們再點選發送請求按鈕,看看這一次請求的頭部資訊:

關于Cookie的知識的總結

請求頭中的Cookie字段是浏覽器發送給伺服器的cookie資訊,cookie的值之前被我們設定為了ok。響應頭中的Set-Cookie字段是伺服器傳回給浏覽器的cookie資訊(實際上這時,cookie的值又被設定為了test)(我隻是描述這個現象,不知道了解的對不對。)。

沒有删除已有cookie的直接方法。是以,需要使用相同的路徑(path)、域(domain)和安全選項(secure)再次設定原cookie,并将失效時間設定為過去時間。

通過document.cookie設定的cookie也會被浏覽器添加到請求頭中。

舉例,用document.cookie設定cookie:

子cookie是存放在單個cookie中的更小段的資料。也就是使用cookie值來存儲多個名值對兒。

一種子cookie的格式:

本質上還是字元串的操作。

(摘自阮一峰老師的文章:跨域資源共享 CORS 詳解)

CORS請求預設不發送Cookie和HTTP認證資訊。如果要把Cookie發到伺服器,一方面要伺服器同意,指定Access-Control-Allow-Credentials字段為true。另一方面,開發者必須在AJAX請求中打開XMLHttpRequest對象的withCredentials屬性。否則,即使伺服器同意發送Cookie,浏覽器也不會發送。或者,伺服器要求設定Cookie,浏覽器也不會處理。

但是,如果省略withCredentials設定,有的浏覽器還是會一起發送Cookie。這時,可以顯式關閉withCredentials。

需要注意的是,如果要發送Cookie,Access-Control-Allow-Origin就不能設為星号,必須指定明确的、與請求網頁一緻的域名。同時,Cookie依然遵循同源政策,隻有用伺服器域名設定的Cookie才會上傳,其他域名的Cookie并不會上傳,且(跨源)原網頁代碼中的document.cookie也無法讀取伺服器域名下的Cookie。

      本文轉自zsdnr  51CTO部落格,原文連結:http://blog.51cto.com/12942149/1928948,如需轉載請自行聯系原作者