瀏覽器專題系列 —— 本地存儲(chǔ):cookie,localStorage,sessionStorage,i...
在目前的現(xiàn)代瀏覽器中主要有以下幾種存儲(chǔ)方案
- cookie
- localStorage
- sessionStorage
- indexDB
下面為大家詳細(xì)道來各種方案的適用場景與缺點(diǎn)
Cookie簡介
主要為了辨別用戶身份而儲(chǔ)存在用戶本地終端上的數(shù)據(jù)
可以記錄用戶對(duì)網(wǎng)站的訪問情況(停留時(shí)長,訪問深度,記錄賬號(hào)密碼,在線狀態(tài)等)
主要由服務(wù)端生成然后下發(fā),客戶端也可控制其內(nèi)容
每次發(fā)送請求都會(huì)自動(dòng)攜帶對(duì)應(yīng)域名的cookie
如何使用
服務(wù)端
服務(wù)端在響應(yīng)頭(Response Header)中添加一個(gè)Set-Cookie字段
示例
Set-Cookie:"name=value;expires=session;path=/;domain=.sugarat.top;HttpOnly;secure;sameSite=lax"
客戶端(瀏覽器)
document.cookie
可以通過此 API獲取或者修改cookie
Set-Cookie
?Set-Cookie 字段的屬性介紹
| cookie屬性 | 簡介 | 特殊說明 |
|---|---|---|
| name | 鍵 | - |
| value | 值 | - |
| Expires | 過期時(shí)間 | 一個(gè)固定的時(shí)間 |
| Max-Age | 過期時(shí)間 | 收到此cookie后多久后過期,優(yōu)先級(jí)大于Expires |
| Domain | 可以送達(dá)的主機(jī)名(域名) | - |
| path | 生效路徑 | 路徑必須出現(xiàn)在要請求的資源的路徑中才可以發(fā)送 |
| Secure | 安全標(biāo)志 | 只有使用HTTPS協(xié)議的時(shí)候才會(huì)攜帶此cookie |
| HTTPOnly | 安全標(biāo)志 | 不允許使用腳本去更改/獲取這個(gè)cookie |
| SameSite | 安全標(biāo)志 | 控制跨站請求獲取cookie |
?屬性補(bǔ)充說明
- Expires:其值為默認(rèn)session,即關(guān)閉瀏覽器時(shí)此cookie就過期失效
- Max-Age:不同取值范圍不同效果
- 大于0:會(huì)將cookie存到本地文件中
- 等于0:立即刪除
- 小于0:等價(jià)于會(huì)話性cookie
- 優(yōu)先級(jí)大于Expires
- Domain:指定了 Cookie 可以送達(dá)的主機(jī)名
- 沒有指定:默認(rèn)值為當(dāng)前文檔訪問地址中的主機(jī)部分(不包含子域名)
- 如果設(shè)置為
.a.com那么a.com,a.a.com,b.a.com等都能訪問,即a.com的子域名都可以訪問到這個(gè)cokie
- HTTPOnly
- 防止客戶端腳本通過
document.cookie方式訪問或者更改 此Cookie - 有助于避免 XSS 攻擊
- 防止客戶端腳本通過
- SameSite:可以設(shè)置讓 Cookie 在跨站請求時(shí)不會(huì)被發(fā)送,從而可以阻止跨站請求偽造攻擊(CSRF)
- Strict:僅允許一方請求攜帶 Cookie,即瀏覽器將只發(fā)送相同站點(diǎn)請求的 Cookie,當(dāng)前網(wǎng)頁 URL 與請求目標(biāo) URL 完全一致才發(fā)送
- Lax:允許部(導(dǎo)航到目標(biāo)網(wǎng)址的 Get 請求)分第三方請求攜帶 Cookie
- None:無論是否跨站都會(huì)發(fā)送 Cookie
- 之前默認(rèn)值是 None ,在Chrome穩(wěn)定版80及更高版本上默認(rèn)是 Lax
?SameSite = lax 的影響
Set-Cookie:'name=value;SameSite=Lax;'
大多數(shù)情況不發(fā)送第三方 Cookie,但是導(dǎo)航到目標(biāo)網(wǎng)址的 Get 請求除外
- 超鏈接
- GET表單
- 預(yù)加載請求
| 請求類型 | 示例 | SameSite = lax 是否發(fā)送cooie |
|---|---|---|
| 超鏈接 | :white_check_mark: | |
| GET表單 | :white_check_mark: | |
| 預(yù)加載 | :white_check_mark: | |
| POST 表單 | :x: | |
| image | :x: | |
| iframe | :x: | |
| ajax | fetch(url) | :x: |
?Cookie 的作用域
Domain 和 Path 標(biāo)識(shí)共同定義了 Cookie 的作用域:即哪些URL的請求 會(huì)攜帶 目標(biāo)Cookie
用途
- 會(huì)話狀態(tài)管理:(如用戶登錄狀態(tài)、賬號(hào)信息等)
- 個(gè)性化設(shè)置:(如用戶自定義設(shè)置、主題等)
- 用戶行為分析:埋點(diǎn)系統(tǒng)(訪問深度,停留時(shí)長等)
缺點(diǎn)
- 容量問題:有上限,最大只能有 4KB
- 性能問題:同一個(gè)域名下的所有請求,都會(huì)攜帶 Cookie,某些請求(a,img,link等標(biāo)簽發(fā)出的請求)可能不需要此cookie,會(huì)加大傳輸?shù)念^部,損耗一定時(shí)空開銷
- 安全問題:客戶端可以通過一定手段(腳本,devtools,本地存儲(chǔ)的文件,修改host文件)獲取到,存在XSS,CSRF等安全問題
解決安全問題的方案
- 減短cookie的有效時(shí)間
- 添加HttpOnly屬性:防止本地腳本讀取cookie
- 服務(wù)端對(duì)傳送的cookie加密
- 添加Secure屬性:使用https協(xié)議傳輸
- 設(shè)置samesite屬性為需要的值:嚴(yán)格卡控cookie的攜帶范圍
瀏覽器提供的數(shù)據(jù)存儲(chǔ)API,作用相同,生命周期與作用域的不同
window.sessionStorage.setItem()
window.localStorage.setItem()
window.sessionStorage.getItem()
window.localStorage.getItem()
生命周期
- localStorage 是持久化的本地存儲(chǔ),永遠(yuǎn)不會(huì)過期,除非手動(dòng)刪除
- sessionStorage 是臨時(shí)性的本地存儲(chǔ),在會(huì)話結(jié)束時(shí)(關(guān)閉頁面),存儲(chǔ)的內(nèi)容就被釋放
作用域
Local Storage、Session Storage 和 Cookie 都遵循同源策略
但Session Storage有特殊之處:即便是相同域名下的兩個(gè)頁面,只要它們不在瀏覽器的同一個(gè)Tab中打開,那么它們的 Session Storage 內(nèi)容便無法共享
優(yōu)點(diǎn)
- 存儲(chǔ)容量大:不同瀏覽器,存儲(chǔ)容量可以達(dá)到 5-10M,針對(duì)一個(gè)域名
- 存儲(chǔ)于客戶端,不會(huì)服務(wù)端發(fā)生通信
缺點(diǎn)
- 只能存儲(chǔ)字符串,JSON對(duì)象需要轉(zhuǎn)換為json string 存儲(chǔ)
- 只適用于存儲(chǔ)少量簡單數(shù)據(jù)
- localStorage需要手動(dòng)刪除
應(yīng)用場景
- base64圖片存儲(chǔ):存儲(chǔ)logo
- 接口數(shù)據(jù)持久化:對(duì)于依賴于接口(變動(dòng)周期比較長)生成的內(nèi)容,可以使用storage存儲(chǔ),以加快首屏渲染
- 常見于一些依賴于接口生成的菜單欄
運(yùn)行在瀏覽器上的非關(guān)系型數(shù)據(jù)庫
依舊受同源策略限制
優(yōu)點(diǎn)
- 理論上沒有存儲(chǔ)上線
- 可以存儲(chǔ)字符串,還可以存儲(chǔ)二進(jìn)制數(shù)據(jù)
- 瀏覽器提供了一套可簡單操作的API
應(yīng)用場景
- 當(dāng)數(shù)據(jù)的復(fù)雜度和規(guī)模上升到了 LocalStorage 無法解決的程度,就使用IndexDB
- 臨時(shí)存儲(chǔ)復(fù)雜的數(shù)據(jù),如頁面中的臨時(shí)文章
- 一些復(fù)雜表單內(nèi)容的離線保存
- 一些依賴狀態(tài)記錄的復(fù)雜離線應(yīng)用
使用教程
筆者這里就不贅述如何使用了,網(wǎng)上有更優(yōu)秀的使用教程
這里給大家推薦兩個(gè),外鏈參看末尾的參考資料
- MDN:使用 IndexedDB[1]
- 阮一峰:瀏覽器數(shù)據(jù)庫 IndexedDB 入門教程[2]
參考資料
[1]MDN:使用 IndexedDB: https://developer.mozilla.org/zh-CN/docs/Web/API/IndexedDB_API/Using_IndexedDB
[2]阮一峰:瀏覽器數(shù)據(jù)庫 IndexedDB 入門教程: http://www.ruanyifeng.com/blog/2018/07/indexeddb.html
[3]SameSite update 日志: https://www.chromium.org/updates/same-site
[4]devTools Storage: https://developers.google.com/web/tools/chrome-devtools/storage/cookies
[5]Chrome Platform Status: https://www.chromestatus.com/feature/5088147346030592
[6]SameSite cookies explained: https://web.dev/samesite-cookies-explained/
