什麼是 Cookie
Cookie(複數形態Cookies),中文名稱為“小型文字檔案”或“小甜餅”,指某些網站為了辨別使用者身份而儲存在使用者本地終端(Client Side)上的資料(通常經過加密)。
這是維基百科對 Cookie 的詞條解釋,由此我們可以知道,Cookie 其實是一個儲存在本地的一個小檔案。
Cookie 的起源
早期 Web 開發面臨的最大問題之一是如何管理狀態。簡言之,伺服器端沒有辦法知道兩個請求是否來自於同一個瀏覽器。那時的辦法是在請求的頁面中插入一個token
,並且在下一次請求中將這個token
返回(至伺服器)。這就需要在form
中插入一個包含token
的隱藏表單域,或著在URL
的qurey
字串中傳遞該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=Strict
、SameSite=Lax
:
允許伺服器設定一則 Cookie 不隨著跨域請求一起傳送,這樣可以在一定程度上防範跨站請求偽造攻擊(CSRF)。
用法
response.setHeader('Set-Cookie', `sign_in_email=${email}`)
複製程式碼
當我們模擬登陸時,就可以看到響應頭裡面的 Cookie
同樣,在跳轉網站請求頭中也可以看到這個 Cookie
- 利用JavaScript來修改Cookie
如果沒有設定不允許修改 Cookie 的話,是可以利用 JavaScript 來修改 Cookie
document.cookie="sign_in_email=789@yyzcl.com"
複製程式碼
此時重新整理頁面看看
此時可以看到,Cookie 被 JavaScript 修改了
但可以通過設定禁止 JavaScript 來修改 Cookie
response.setHeader('Set-Cookie', `sign_in_email=${email}; HttpOnly`)
複製程式碼
這樣就無法通過 JavaScript 來修改 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。
-
伺服器可以通過
Expires
、max-age
這兩個標籤將 Cookie 設定成過期的狀態,之後瀏覽器會自動清除 -
JavaScript 可以通過
document.cookie
來操作 Cookie 刪除 -
可以通過瀏覽器手動刪除
後話
我也是接觸 Cookie 不久,對其還不是很熟悉,還有很多地方值得去探討