一、Cookie介紹
因為HTTP協議是無狀態的,每次請求都是獨立的,服務器端無法判斷兩次請求是否來自同一個用戶,進而也就無法判斷用戶的登錄狀態,也不知道用戶上一次做了什么。所以Cookie就是用來繞開HTTP的無狀態性的“額外手段”之一。服務器可以設置或讀取Cookies中包含信息,借此維護用戶跟服務器會話中的狀態。
Cookie 是服務器端發送給客戶端的一段特殊信息,這些信息以文本的方式存放在客戶端,客戶端每次向服務器端發送請求時都會帶上這些特殊信息。
具體過程是:客戶端發送請求到服務端,然后服務端返回的response headers中會有Set-Cookie這個字段,將 信息寫入 Cookie 中。然后在下一次客戶端請求接口時,會在request headers里帶上這個Cookie字段,這樣服務器就可以拿到這些信息,達到了維持狀態的目的。


Cookie 主要用於以下三個方面:
- 會話狀態管理(如用戶登錄狀態、購物車、游戲分數或其它需要記錄的信息)
- 個性化設置(如用戶自定義設置、主題等)
- 瀏覽器行為跟蹤(如跟蹤分析用戶行為等)
二、Cookie的屬性
2.1 domain和path屬性
domain 指定了該 Cookie 所屬的域名,默認情況下,domain 會被設置為創建該 Cookie 時所在的域名。如果不指定,默認為 origin,不包含子域名。如果指定了Domain,則一般包含子域名。
例如,如果設置 Domain=mozilla.org,則 Cookie 也包含在子域名中(如developer.mozilla.org)。
而 path 則指定了該 Cookie 所屬的路徑,注意子路徑也會被匹配。
例如,設置 Path=/docs,則/docs/Web/ 這個地址也會匹配。
domain 和 path 兩者一起來限制了該 Cookie 允許被哪些 URL 訪問。
2.2 Expires/Max-Age
Expires :具體到期時間,UTC格式。如果沒有設置該選項,則默認有效期為session,即會話cookie,這種cookie在瀏覽器關閉后就沒有了。
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;
Max-Age屬性指定從現在開始 Cookie 存在的秒數,比如60 * 60 * 24 * 365(即一年)。過了這個時間以后,瀏覽器就不再保留這個 Cookie。
如果同時指定了Expires和Max-Age,那么Max-Age的值將優先生效。
- Max-Age為正數: cookie 會在 max-age 秒之后被銷毀
- Max-Age為負數時: cookie 只在瀏覽器會話期間存在,當用戶關閉瀏覽器窗口后這些值也會隨之銷毀
- Max-Age 為 0 時: cookie 將被立即銷毀
2.3 SameSite屬性
SameSite: Cookie 允許服務器要求某個 cookie 在跨站請求時不會被發送,從而可以阻止跨站請求偽造攻擊(CSRF)。
SameSite 可以有下面三種值:
- None。瀏覽器會在同站請求、跨站請求下繼續發送 cookies,不區分大小寫。
- Strict。瀏覽器將只發送相同站點請求的 Cookie(即當前網頁 URL 與請求目標 URL 完全一致)。
- Lax。在新版本瀏覽器中,為默認選項,Same-site Cookies 將會為一些跨站子請求保留,如圖片加載或者 iframe 不會發送,而點擊 a 標簽會發送;
大多數主流瀏覽器的SameSite的默認值已經是Lax了。如果想要指定 Cookies 在同站、跨站請求都被發送,現在需要明確指定 SameSite 為 None。(所以不要再問為什么接口返回了Set-Cookie但是卻沒有設置成功了,大概率原因在這里,曾經遇到過。本地開發的話在chrome://flags中把SameSite by default cookies設為Disabled即可解決,可正常開發,上線的話一般不會跨域,即不會出現這個問題,如果出現跨域就只能讓后端改了domain字段了)
2.4 HttpOnly
如果這個屬性設置為true,意思就是告之瀏覽器該 cookie 絕不能通過 JavaScript 的 document.cookie 屬性訪問。可以避免跨域腳本 (XSS) 攻擊。
(面試高頻)
2.5 Secure
標記為 Secure的 Cookie 只應通過被 HTTPS 協議加密過的請求發送給服務端。
三、Cookie相關操作
1.創建Cookie:
// 直接使用document.cookie = 設置即可
document.cookie= "test=" + '123';
2.讀取Cookie:
直接調用函數,例如let cookie = getCookie(); cookie.name即為對應cookie。
// 讀取Cookie函數
function getCookie() {
let cookieArr = document.cookie.split("; "); // 特別注意!cookie中的數據都是以分號加空格區分開
let obj = {};
cookieArr.forEach( v => {
let arr = v.split("=");
obj[arr[0]] = unescape(arr[1]); // unescape 解碼
});
return obj
}
3.刪除Cookie:
直接調用:delCookie("xxx");
//刪除Cookie
function delCookie(name){
// 將 cookie 的 max-age 屬性設置 0 來實現對 cookie 的刪除
document.cookie = `${name}=;max-age=0`;
}
在ios系統上面,設置Cookie為漢字時會設置失敗,所以需要將漢字進行編碼,再儲存到Cookie,取出來的時候也需要解碼,encode:escape(),decode:unescape()。
四、其他
- Cookie是跨域的,也就是在不同的域名中,訪問的Cookie的時候,只能訪問對應的域名的Cookie。
- 每個Cookie的大小一般不超過4KB,超過以后,Cookie將會被忽略,不會被設置
- 瀏覽器每次向服務器發起請求,就會自動附上Cookie
更多文章以及分享請關注微信公眾號 前端er的分享,不止於前端,定期輸出一些技術知識、生活感想、理財知識等。
