cookie 簡介

導讀

思惟導圖

1、 簡介

首先要知道標準的 http 協議是無狀態的,也就是指服務端對於客戶端的每次請求都認爲它是一個新的請求,上一次會話和下一次會話之間是沒有任何聯繫,這時當用戶訪問服務端並進行登陸後,客戶端以後的請求服務端依然沒法對客戶端身份進行識別, 若是將客戶端與服務器之間的屢次交互當作一個總體來看,那麼服務端若想識別客戶端的身份那麼就須要將屢次交互所涉及的數據(狀態)保存下來。 cookie 的做用就是對請求和響應的狀態進行一個管理, 服務端經過在響應體中設置 cookie (狀態), 客戶端會將 cookie (狀態) 存儲起來, 以後客戶端的每一個請求都將 cookie (狀態)帶上, 這樣服務端就可以對客戶端的身份進行識別;在早期 cookie 還未出現以前有個最簡單的辦法就是在請求的頁面中插入一個 token,而後在下次請求時將這個 token 返回至服務器。這須要在頁面的 form 表單中插入一個包含 token 的隱藏域,或者將 token 放在 URL 的 query 字符串中來傳遞。這兩種方法都須要手動操做,並且極易出錯, 而 cookie 則不一樣通常狀況下客戶端會自動存儲服務器發來的 cookie, 並在以後的每次請求中自動帶上 cookie 而無需客戶端進行手動處理。前端

補充: 標準的http協議指的是不包括cookies, session,application的http協議,他們都不屬於標準協議,雖然各類網絡應用提供商,實現語言、web容器等,都默認支持它。node

2、 基本原理

原理圖

當瀏覽器向服務器發送請求的時候,服務器會將少許的數據以 set-cookie 消息頭的方式發送給客戶端, 瀏覽器通常會自動將 cookie 數據進行存儲,當客戶端再次訪問服務器時,會將這些數據以 cookie 消息頭的方式發送給服務器,服務端就能夠根據 cookie 消息頭來判別用戶的身份或進行一些特別的處理並返回響應。web

3、 生存期

從 cookie 的工做原理上能夠知道 cookie 信息主要是存儲在客戶端的狀態, 而 cookie 在客戶端的生存期則主要由屬性 max-age 決定, max-age 屬性以秒爲單位表示 cookie 的存活時間爲 max-age 秒; 固然 cookie 還有一個屬性 expires 其做用和 max-age 是同樣的這在後續會進行詳細說明。chrome

  • 默認狀況下 cookie 只是暫時存在的,他們存儲的值只在瀏覽器會話期間存在,當用戶關閉瀏覽器窗口後這些值也會隨之銷燬(生成的 cookie 臨時存儲於瀏覽器內存中)
  • max-age 爲正數: cookie 會在 max-age 秒以後被銷燬(會將狀態存儲於 cookie 文件中並存儲於本地硬盤中)
  • max-age 爲負數時: cookie 只在瀏覽器會話期間存在,當用戶關閉瀏覽器窗口後這些值也會隨之銷燬(生成的 cookie 臨時存儲於瀏覽器內存中)
  • max-age 爲 0 時: cookie 將被當即銷燬

4、 各大瀏覽器支持狀況

IE 6 IE 7.0 8.0 Opera Fire Fox Safari   Chrome 
cookie 個數 每一個域名下20個 每一個域名下50個 每一個域名30個 每一個域名50個 沒有限制 每一個域名53個
cookie 大小 4095字節 4095字節 4096字節 4097字節 4097字節 4097字節

5、 屬性介紹

上文說到 cookie 主要是用於管理服務端和客戶端直接的狀態, 其本質上就是一堆存儲在客戶端的數據, 每條 cookie 都有對應下面幾個屬性:api

5.1 domain 和 path 屬性

domain 指定了該 cookie 所屬的域名,默認狀況下,domain 會被設置爲建立該 cookie 時所在的域名; 而 path 則指定了該 cookie 所屬的路徑; domain 和 path 二者一塊兒來限制了該 cookie 容許被哪些 URL 訪問, 當咱們請求某個資源(URL)時只有當該 URL 域名可以同時被 domain 和 path 屬性匹配時, 瀏覽器纔會將此 cookie 添加到該請求的 cookie 頭部中。跨域

domain 的匹配是根據請求 URL 中的域名從後向前進行匹配, path 的匹配則是根據 URL 中的路徑按照路徑的匹配規則判斷 URL 中的路徑是否包含 path, 例如:數組

domain 屬性 path 屬性 請求 URL 請求是否包含 cookie 描述
auth.com / b.auth.com/a/d -
b.auth.com /a b.auth.com/a/b -
b.auth.com /b b.auth.com/a/b path 屬性不匹配,路徑 /a/b 不包含 /b
b.auth.com /c b.auth.com/a/b path 屬性不匹配,路徑 /a/b 不包含 /c
a.auth.com / b.auth.com/a/b domain 不匹配

5.2 expires/max-age

首先須要知道清楚 expires 是 http/1.0 協議中的屬性,在新的 http/1.1 協議以後 expires 已經由 max-age 選項代替,二者的做用都是限制 cookie 的有效時間。瀏覽器

expires 屬性指定一個具體的到期時間,到了指定時間之後,瀏覽器就再也不保留這個 cookie 。它的值是 UTC 格式,可使用 Date.prototype.toUTCString() 進行格式轉換。而 max-age 屬性則是指定從如今開始 cookie 存在的秒數,好比 60 * 60 * 24 * 365 (即一年)。過了這個時間之後,瀏覽器就再也不保留這個 cookie 。若是同時指定了 expires 和 max-age,那麼 max-age 的值將優先生效。若是沒有指定 expires 或 max-age 屬性,那麼這個 cookie 就是 Session Cookie, 即它只在本次對話存在,一旦用戶關閉瀏覽器窗口, 瀏覽器將不會再保留這個 cookie 。安全

5.3 secure

該屬性只是一個標記而沒有值。包含 secure 選項的 cookie 只有在當請求是 HTTPS 或者其餘安全協議時, 才能被髮送至服務器。默認狀況下, cookie 不會帶 secure 選項(即爲空)。因此默認狀況下,不論是 HTTPS 協議仍是 HTTP 協議的請求,cookie 都會被髮送至服務端。但要注意一點,secure 選項只是限定了在安全狀況下才能夠傳輸給服務端,但並不表明你不能看到這個 cookie。同時須要注意的是, 若是想在客戶端即網頁中經過 js 去設置 secure 類型的 cookie,必須保證網頁是 https 協議的。在http協議的網頁中是沒法設置 secure 類型 cookie 的。服務器

5.4 httpOnly

httpOnly 背後的意思是告之瀏覽器該 cookie 毫不能經過 JavaScript 的 document.cookie 屬性訪問。設計該特徵意在提供一個安全措施來幫助阻止經過 JavaScript 發起的跨站腳本攻擊 (XSS) 竊取 cookie 的行爲, 一旦設定這個標記,經過 documen.coookie 則不能再訪問該 cookie。

5.5 sameSite

sameSite-cookies 是一種機制,用於定義 cookie 如何跨域發送,其目的主要是爲了嘗試阻止 CSRF (Cross-site request forgery 跨站請求僞造)以及 XSSI (Cross Site Script Inclusion (XSSI) 跨站腳本包含)攻擊。

CSRF攻擊簡述: CSRF 攻擊主要是盜用用戶信息併發送惡意請求的一種攻擊方式, 好比說某用戶登陸一個徹底網站 A, A 站點返回一個可以標識用戶身份的 cookie, 當用戶無心中訪問一個惡意網站 B, B 站點向 A 站點發起惡意請求, 這時請求中將會帶上具備用戶身份標識的 cookie。

XSSI攻擊簡述: XSSI 是 XSS 的一種形式, 假設網站 A 有一個腳本用於讀取用戶的私人帳戶信息, 攻擊者能夠在本身的惡意網站包含這個腳本, 當網站 A 的用戶訪問攻擊者的網站時該網站將加載該腳本並帶上用戶身份標識 (cookie) 該腳本將讀取用戶的私人帳戶信息, 這時用戶的信息可能就會發生泄露。

sameSite 屬性可能值: 爲 cookie 設置 sameSite 屬性時須要給其定義一個值(若是沒有設置值,默認是Strict),值能夠是 Lax 或者 Strict

strict: 當 sameSite 屬性值爲 strict 時, 將禁止發送全部第三方連接的 cookies, 好比有 cookie ( domain = a.com, sameSite = strict ), 那麼在其餘網站請求 a.com 時都不會帶上該 cookie

lax: 當 sameSite 屬性值爲 lax 時, 只會在使用危險 HTTP 方法發送跨域 cookie 的時候進行阻止,例如 POST 方式。好比有 cookie ( domain = a.com, sameSite = lax ), 那麼在其餘網站經過 POST 方式請求 a.com 時都不會帶上該 cookie

6、 前端操做 cookie

6.1 建立 cookie

前端經過 document.cookie 設置 cookie, 設置多個 cookie 則須要編寫多條 document.cookie = '...', 若是須要對 cookie 進行修改建立一條相同名稱的 cookie 便可對 cookie 進行替換

// 建立多條 cookie 並設置 path 和 domain 以及 max-age 屬性
document.cookie = 'name1=value1;path=/;domain=localhost;max-age=30';
document.cookie = 'name2=value2;path=/;domain=localhost;max-age=30';
document.cookie = 'name3=value3;path=/;domain=localhost;max-age=30';

/** * 通用方法: 設置 cookie 方法 * @param {String} name cookie 名稱 * @param {String} value cookie 值 * @param {Number} maxAge cookie 存活時間(maxAge秒, 默認存儲 30 天) */
function setCookie({name, value, maxAge}) {
  maxAge = maxAge || 30*24*60*60*1000;
  // escape: 對字符串進行編碼
  document.cookie = `${name}=${escape (value)};max-age=${maxAge}`;
}
複製代碼

經過瀏覽器(chrome)控制檯查看 cookie 信息

cookie信息

6.2 獲取 cookie

前端可直接經過 document.cookie 獲取 cookie

// 打印 cookie
console.log(document.cookie); // name1=value1; name2=value2; name3=value3

/** * 通用方法: 將 cookie 轉爲對象 {anme: value} * @return {Object} {name, value} */
function getCookieObj() {
  let cookieArr = document.cookie.split(";");
  let obj = {};
  cookieArr.forEach( v => {
    let arr = v.split("=");
    obj[arr[0]] =  unescape(arr[1]);
  });
  return obj
}
複製代碼

6.3 刪除 cookie

前端並無直接的 api 能夠直接實現對 cookie 的刪除, 能夠經過將 cookie 的 max-age 屬性設置 0 來實現對 cookie 的刪除

// 刪除 cookie
document.cookie = 'name3=value3;max-age=0';

/** * 通用方法: 刪除 cookie 方法 * @param {String} name cookie 名稱 */
function delCookie({ name }) {
  document.cookie = `${name}=;max-age=0`;
}
複製代碼

7、 服務端操做 cookie

7.1 設置 cookie

服務端設置 cookie 主要是經過設置響應頭 set-cookie 來設置 cookie, 若是須要設置多個 cookie 得多寫幾個 set-cookie

// 1. koa 中直接經過設置請求頭的方式設置 cookie
// 2. 在 node 中 response 響應中設置兩次相同的 header 屬性會發生合併, 能夠經過一個數組來實現
ctx.set(
  'Set-cookie',
  'name=value;path=/user;domain=localhost;max-age=30;HttpOnly;SameSite=Strict'
);
複製代碼

查看響應頭

響應頭

查看瀏覽器控制檯

控制檯

7.2 獲取 cookie

服務器獲取 cookie 實際上就是獲取請求頭 cookie

// koa 中獲取請求頭信息並進行打印(獲取的 cookie 格式和前端獲取到的格式是同樣的因此也就能夠經過相同的方式來處理)
console.log(ctx.request.headers.cookie); // name1=value1; name2=value2; name3=value3
複製代碼

查看請求頭信息

請求頭
相關文章
相關標籤/搜索