初次接觸 Cookie

YyzclYang發表於2018-08-14

什麼是 Cookie

Cookie(複數形態Cookies),中文名稱為“小型文字檔案”或“小甜餅”,指某些網站為了辨別使用者身份而儲存在使用者本地終端(Client Side)上的資料(通常經過加密)。

這是維基百科對 Cookie 的詞條解釋,由此我們可以知道,Cookie 其實是一個儲存在本地的一個小檔案。

Cookie 的起源

早期 Web 開發面臨的最大問題之一是如何管理狀態。簡言之,伺服器端沒有辦法知道兩個請求是否來自於同一個瀏覽器。那時的辦法是在請求的頁面中插入一個token,並且在下一次請求中將這個token返回(至伺服器)。這就需要在form中插入一個包含token的隱藏表單域,或著在URLqurey字串中傳遞該token。這兩種辦法都強調手工操作並且極易出錯。

Lou Montulli,那時是網景通訊的一個僱員,被認為在1994年將 “magic cookies” 的概念應用到了 Web 通訊中。他意圖解決的是 Web 中的購物車,現在所有購物網站都依賴購物車。他的最早的說明文件提供了一些 Cookies 工作原理的基本資訊該文件在 RFC2109 中被規範化(這是所有瀏覽器實現 Cookies 的參考依據),並且最終逐步形成了REF2965。Montulli 最終也被授予了關於 Cookies 的美國專利。網景瀏覽器在它的第一個版本中就開始支援 Cookies,並且當前所有 Web 瀏覽器都支援 Cookies。

Cookie 的特點

伺服器通過Set-Cookie響應頭設定 Cookie

瀏覽器得到 Cookie 之後,每次請求都要帶上 Cookie,無形中增加了流量

伺服器讀取 Cookie 就知道登入使用者的資訊

由於在 HTTP 請求中的 Cookie 是明文傳遞的,所以安全性成問題,除非用 HTTPS

Cookie 的大小限制在 4KB 左右,對於複雜的儲存需求來說是不夠用的

除了這些特點之外,還有

不同瀏覽器的 Cookie 不共享

Windows 的 Cookie 儲存在C盤的一個資料夾中

Cookie 可以作假

Cookie 有有效期,一般是20分鐘。瀏覽器可自行設定,後端也可以強制設定有效期

後端可以設定 Cookie 的有效期,是否只允許 HTTPS 連結,是否允許 JS 修改等等

如何設定 Cookie

語法

Set-Cookie: <cookie-name>=<cookie-value> 
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: <cookie-name>=<cookie-value>; SameSite=Strict
Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Lax
複製程式碼

在 Cookie 的設定中,後面的選項是可選的,且可同時多選。

  • 解釋

<cookie-name>=<cookie-value>
<cookie-name> 可以是除了控制字元 (CTLs)、空格 (spaces) 或製表符 (tab)之外的任何 US-ASCII 字元。同時不能包含以下分隔字元: ( ) < > @ , ; : \ " / [ ] ? = { }。
<cookie-value> 是可選的,如果存在的話,那麼需要包含在雙引號裡面。支援除了控制字元(CTLs)、空格(whitespace)、雙引號(double quotes)、逗號(comma)、分號(semicolon)以及反斜線(backslash)之外的任意 US-ASCII 字元。

Expires=<date>
Cookie 的最長有效時間,形式為符合 HTTP-date 規範的時間戳。如果沒有設定這個屬性,那麼表示這是一個會話期 Cookie 。一個會話結束於客戶端被關閉時,這意味著會話期 Cookie 在彼時會被移除。

Max-Age=<non-zero-digit>
在 Cookie 失效之前需要經過的秒數。一位或多位非零(1-9)數字。

Domain=<domain-value>
指定 Cookie 可以送達的主機名。假如沒有指定,那麼預設值為當前文件訪問地址中的主機部分(但是不包含子域名)。

Path=<path-value>
指定一個 URL 路徑,這個路徑必須出現在要請求的資源的路徑中才可以傳送 Cookie 首部。

Secure
一個帶有安全屬性的 Cookie 只有在請求使用 SSL 和 HTTPS 協議的時候才會被髮送到伺服器。然而,保密或敏感資訊永遠不要在 HTTP Cookie 中儲存或傳輸,因為整個機制從本質上來說都是不安全的,比如前述協議並不意味著所有的資訊都是經過加密的。

HttpOnly
設定了 HttpOnly 屬性的 Cookie 不能使用 JavaScript 經由 Document.cookie 屬性、XMLHttpRequest 和 Request APIs 進行訪問,以防範跨站指令碼攻擊(XSS)。

SameSite=StrictSameSite=Lax
允許伺服器設定一則 Cookie 不隨著跨域請求一起傳送,這樣可以在一定程度上防範跨站請求偽造攻擊(CSRF)。

用法

response.setHeader('Set-Cookie', `sign_in_email=${email}`)
複製程式碼

當我們模擬登陸時,就可以看到響應頭裡面的 Cookie

初次接觸 Cookie

同樣,在跳轉網站請求頭中也可以看到這個 Cookie

初次接觸 Cookie

  • 利用JavaScript來修改Cookie

如果沒有設定不允許修改 Cookie 的話,是可以利用 JavaScript 來修改 Cookie

document.cookie="sign_in_email=789@yyzcl.com"
複製程式碼

此時重新整理頁面看看

初次接觸 Cookie

此時可以看到,Cookie 被 JavaScript 修改了

但可以通過設定禁止 JavaScript 來修改 Cookie

response.setHeader('Set-Cookie', `sign_in_email=${email}; HttpOnly`)
複製程式碼

這樣就無法通過 JavaScript 來修改 Cookie

初次接觸 Cookie

但是還是可以手動地來修改

初次接觸 Cookie

再重新整理頁面看看

初次接觸 Cookie

Cookie是可以人為地偽造地,所以說 Cookie 是不安全的

設定過期時間

可以通過 Cookie 的以下屬性來設定過期時間。

Set-Cookie: <cookie-name>=<cookie-value>; Expires=<date>
Set-Cookie: <cookie-name>=<cookie-value>; Max-Age=<non-zero-digit>
複製程式碼
  • Expires指定了一個日期/時間, 在這個日期/時間之後 Cookie 過期

  • max-age指定了一個秒數,經過此秒數後 Cookie 過期

  • 如果不設定這個標頭,則預設關閉瀏覽器後 Cookie 過期

刪除 Cookie

有多種方式來刪除 Cookie。

  • 伺服器可以通過Expiresmax-age這兩個標籤將 Cookie 設定成過期的狀態,之後瀏覽器會自動清除

  • JavaScript 可以通過document.cookie來操作 Cookie 刪除

  • 可以通過瀏覽器手動刪除

後話

我也是接觸 Cookie 不久,對其還不是很熟悉,還有很多地方值得去探討

相關文章