1. 程式人生 > >解密Cookie,這一篇就夠了

解密Cookie,這一篇就夠了

# 一、Cookie介紹 因為HTTP協議是無狀態的,每次請求都是獨立的,伺服器端無法判斷兩次請求是否來自同一個使用者,進而也就無法判斷使用者的登入狀態,也不知道使用者上一次做了什麼。所以Cookie就是用來繞開HTTP的無狀態性的“額外手段”之一。伺服器可以設定或讀取Cookies中包含資訊,藉此維護使用者跟伺服器會話中的狀態。 Cookie 是伺服器端傳送給客戶端的一段特殊資訊,這些資訊以文字的方式存放在客戶端,客戶端每次向伺服器端傳送請求時都會帶上這些特殊資訊。 具體過程是:客戶端傳送請求到服務端,然後服務端返回的response headers中會有Set-Cookie這個欄位,將 資訊寫入 Cookie 中。然後在下一次客戶端請求介面時,會在request headers裡帶上這個Cookie欄位,這樣伺服器就可以拿到這些資訊,達到了維持狀態的目的。 ![螢幕快照 2020-10-21 14.43.46.png](https://cdn.nlark.com/yuque/0/2020/png/1726990/1603262684364-f218636f-2387-4256-87ee-0287261f1de9.png#align=left&display=inline&height=190&margin=%5Bobject%20Object%5D&name=%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202020-10-21%2014.43.46.png&originHeight=258&originWidth=491&size=42575&status=done&style=stroke&width=361)![螢幕快照 2020-10-21 14.43.33.png](https://cdn.nlark.com/yuque/0/2020/png/1726990/1603262688203-21f8b5cd-3e5b-4ab4-a93b-ac2705f137d4.png#align=left&display=inline&height=154&margin=%5Bobject%20Object%5D&name=%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202020-10-21%2014.43.33.png&originHeight=172&originWidth=407&size=27350&status=done&style=stroke&width=364) 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: ```javascript // 直接使用document.cookie = 設定即可 document.cookie= "test=" + '123'; ``` ### 2.讀取Cookie: 直接呼叫函式,例如let cookie = getCookie(); cookie.name即為對應cookie。 ```javascript // 讀取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"); ```javascript //刪除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的分享**,不止於前端,定期輸出一些技術知識、生活感想、理財知識