作者:J
從哪來
瀏覽器新增cookie的時機:
-
有客戶端來設定:通過javascript的api——document.cookie來操作
設定
document.cookie = `name=value; maxAge=3000; path=/; domain=xx.com; secure`複製程式碼
cookie的名和值中不能出現分號、逗號、等號和空格,每一個key之間通過分號和空格來分割。
設定多個cookie
通過document.cookie的方式來設定cookie每次只能設定一個cookie。如果我們寫多個會有什麼效果呢?
document.cookie = `cookie1=value1; cookie2=value2`複製程式碼
放在console中執行一下,會發現,只有第一個cookie1設定成功,而cookie2被無視了。所以要設定多個cookie,最簡單的方式就是多次呼叫document.cookie。
-
由服務端來設定:http的響應頭中。
開啟瀏覽器的控制檯,在network下我們可以看到瀏覽器發出的所有請求。這些請求的返回頭中,有些會發現一個Set-Cookie的欄位。
伺服器通過這個欄位來告訴瀏覽器,它需要設定一個cookie,然後瀏覽器檢查一下要設定的內容是否滿足瀏覽器定下的cookie的“條條框框”,如果滿足那麼一個cookie就誕生了。這裡提到了“條條框框”我們稍後做解答。
在上圖中,響應頭裡set-cookie欄位可以有多個,每一個對應一個要設定的cookie,且只能對應一個。
到哪去
-
客戶端主動獲取
和客戶端設定相同,獲取的時候也是通過document.cookie來讀取:
var cookies = document.cookie複製程式碼
讀取到的cookie為一串字串,每個cookie之間通過分號來分割。
-
隨著請求傳送
瀏覽器傳送請求時,在請求的頭中會自動將“符合條件”的cookie帶上。
既然是請求頭中攜帶的,那麼我們通過ajax傳送請求的時候,能否順便設定一下cookie呢?簡單的實驗一下即可知曉:var xhr = new XMLHttpRequest(); xhr.open(`GET`, url, true); xhr.withCredentials = true; xhr.setRequestHeader(`Cookie`, "key=value"); xhr.send(null);複製程式碼
然後我們看看實際上瀏覽器傳送出去的請求:
我們設定的cookie並沒有生效,並且chrome瀏覽器下我們會看到一行報錯
Refused to set unsafe header “Cookie”
所以說,因為瀏覽器的安全限制,我們不能自己隨便設定請求頭中的cookie。
cookies條條框框
一個cookie除了value外,還有domain、path、expires/max-age、httpOnly、secure、sameSite這些屬性。設定cookie的時候,可以對這些相關屬性進行設定,當然也可以不進行設定,這時瀏覽器會自動給這些屬性一個預設值。cookie的條條框框就和這些屬性脫不了干係。
-
domain
domain限制了cookie的使用範圍:只能在domain值的範圍中才能訪問到該cookie.
同時domain值的設定也有嚴格的要求。
-
自身
毫無疑問domain的值可以設定為本身。
-
向下:所有子域名
如果我們當前頁面的域名是 sub.test.com, 那麼 domain 可以設定為.sub.test.com。允許所有sub.test.com的子域名訪問,如xx.sub.test.com、xx.xx.sub.test.com。
-
向上:父級域名,直到Top-Level的下一級
如果我們當前頁面的域名是sub.test.com, 那麼domain可以設定為test.com。但是不能設定為.com。因為.com屬於Top-Level Domain。
-
-
path
domain+path 共同限制了可訪問該cookie的URL。如果某個cookie的path=`/home`,那麼只有“domain/home”下的所有url可以訪問該cookie。
-
expires/max-age
這兩個值決定了cookie能活多久。如果不進行設定,那麼瀏覽器會預設將cookie的有效期設定為 session,當頁面關閉後cookie便隨之被清理了。如果希望cookie在頁面關閉後,仍然能儲存一段時間,那麼就需要為cookie設定一個過期時間,在過期時間內瀏覽器都會為我們保留該cookie.
expires 是 http/1.0協議中的選項,在新的http/1.1協議中expires已經由 max-age 選項代替。expires必須是 GMT 格式的時間。
max-age的單位為秒,cookie失效時刻 = 建立時刻 + max-age
-
httpOnly
如果一個cookie被標記為httpOnly, 那麼前文所提到的通過document.cookie的方式就無法獲取到該cookie。同樣的,我們通過js來設定cookie的,也無法被標記為httpOnly。也就說以下寫法是不會生效的:
document.cookie="cookie1=value1; HttpOnly"複製程式碼
這個值只能通過請求的響應頭來設定。預設情況下,cookie不會帶httpOnly選項。
-
Secure
對於被標記為Secure的cookie,只有當請求是HTTPS或者其他安全協議時,該cookie 才能被訪問到。同樣的,也只有在HTTPS或者其他安全協議時,我們也才能通過js設定secure的cookie。
-
sameSite
這個值這是谷歌開發的一種安全機制,用來定義cookie如何跨域傳送,其目的是嘗試阻止CSRF。chrome51版本已經支援。關於各大瀏覽器的支援情況,參考chrome官網。關於這個特性,這裡不多做介紹了,感興趣的可參看preventing-csrf-with-samesite-cookie-attribute和goodbye-csrf-samesite-to-the-rescue
最後,這些所有的屬性值,一起決定了一件事——這個cookie那個URL可以能用。
參考文獻:
developers.livechatinc.com/blog/settin…
www.sjoerdlangkemper.nl/2016/04/14/…
歡迎關注DDFE
GITHUB:github.com/DDFE
微信公眾號:微信搜尋公眾號“DDFE”或掃描下面的二維碼