Cookie 詳解以及實現一個 cookie 操作庫

aniiantt發表於2018-10-18

cookie 在前端有著大量的應用,但有時我們對它還是一知半解。下面來看看它的一些具體的用法

Set-Cookie

伺服器通過設定響應頭來設定客戶端的 cookie,形如:

Set-Cookie: <cookie名>=<cookie值>
複製程式碼

可以同時新增多個 Set-Cookie,從而設定多個 cookie 的值。

Set-Cookie 有幾個可選項:

Expires/Max-Age

Expires/Max-Age 可以設定過期時間。Expires 為某個日期 GMT 格式。Max-Age 為需要經過的秒數。優先順序比 Expires 高。沒有設定過期時間,則表示是一個會話期 cookie,在關閉瀏覽器後,會被移除(瀏覽器支援會話恢復,保留 cookie)。設定了後叫做永續性 cookie。

Domain 和 Path

Path 設定必須是匹配的路徑或者子路徑才會傳送 cookie。Domain 標識指定了哪些主機可以接受 Cookie。若沒有設定則是當前主機(不包括子域名)。否則則為設定的域名(包括子域名)。

Secure 和 HttpOnly

Secure 標誌 cookie 只能通過 https 傳輸。可以防止 xss 攻擊。 HttpOnly 表示 cookie 無法通過 javascript 呼叫。 防止中間人劫持。

SameSite

可以設定 SameSite:SameSite=Strict SameSite=Lax。則 cookie 不跨域傳送。

第三方 cookie

如果傳送的請求的域和接送的域不同,則請求仍有可能攜帶目標域的 cookie。如:

new Image.src() = https://google.com/xxxx // 無論該連結是否存在都會傳送
複製程式碼

該請求會將 google 的 cookie 攜帶在請求中傳送到 google 的伺服器上。因此如果 google 只採用 cookie 鑑權的話。那惡意網站就可以為所欲為的進行它想要的操作了。這就是 csrf 的原理之一。

對於 post,ajax 可以標示 withCredentials 從而跨域攜帶 cookie,fetch 可以設定 credentials:'include'。

var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://a.test/hhh12');
xhr.withCredentials = true;
xhr.send();

fetch('http://a.test/hhhaaaaa12', { credentials: 'include' });
複製程式碼

瀏覽器可以關閉第三方 cookie。(如果應用了 p3p 協議則無法關閉)。

通過第三方 cookie 廣告商可以標示使用者,從而進行跟蹤。

javascript 和 cookie

通過 document.cookie 我們可以獲取所有非 http-only 標誌的 cookie。document.cookie = newCookie 可以一個新的 cookie。

現在我們來實現一個 mini 的 cookie 操作庫:

const Minicookie = {
  getItem(cookieName) {
    const cookies = document.cookie;
    const cookieList = cookies ? cookies.split('; ') : [];
    for (const cookieItem of cookieList) {
      const [, _cookieName, _cookieValue] = cookieItem.match(/^(.*?)=(.*)/);
      if (_cookieName === cookieName) {
        return _cookieValue;
      }
    }
    return void 0;
  },
  setItem(key, value) {
    document.cookie = `${key}=${value}`
  },
  removeItem(key) {
    // 通過設定過期時間來實現刪除, path也是必須,因為需要知道作用範圍,沒有設定則會生成一個空的同名屬性。
    document.cookie = `${key}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`
  }
};
複製程式碼

參考連結

相關文章