cookie從哪來到哪去

滴滴出行·DDFE發表於2019-03-04

作者:J

從哪來

瀏覽器新增cookie的時機:

  • 有客戶端來設定:通過javascript的api——document.cookie來操作

    設定
      document.cookie = `name=value; maxAge=3000; path=/; domain=xx.com; secure`複製程式碼

    cookie的名和值中不能出現分號、逗號、等號和空格,每一個key之間通過分號和空格來分割。

    通過document.cookie的方式來設定cookie每次只能設定一個cookie。如果我們寫多個會有什麼效果呢?

      document.cookie = `cookie1=value1; cookie2=value2`複製程式碼

    放在console中執行一下,會發現,只有第一個cookie1設定成功,而cookie2被無視了。所以要設定多個cookie,最簡單的方式就是多次呼叫document.cookie。

  • 由服務端來設定:http的響應頭中。

    開啟瀏覽器的控制檯,在network下我們可以看到瀏覽器發出的所有請求。這些請求的返回頭中,有些會發現一個Set-Cookie的欄位。

    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從哪來到哪去

    我們設定的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-attributegoodbye-csrf-samesite-to-the-rescue

    最後,這些所有的屬性值,一起決定了一件事——這個cookie那個URL可以能用。

參考文獻:
developers.livechatinc.com/blog/settin…
www.sjoerdlangkemper.nl/2016/04/14/…


歡迎關注DDFE
GITHUB:github.com/DDFE
微信公眾號:微信搜尋公眾號“DDFE”或掃描下面的二維碼

cookie從哪來到哪去

相關文章