轉載請註明出處:unclekeith: 前端存儲html
前端存儲是每一個前端開發工程師必備的技能。廢話很少說了,直接進入主題。前端
如下總結有關前端存儲方面的知識。主要是Cookie與WebStorage。固然,對於這兩種存儲方式的介紹,會與前端安全的問題一塊兒討論web
Cookie,中文名稱爲'小型文本文件'或'小甜餅',指某些網站爲了辨識用戶身份而存儲在用戶本地終端上的數據(一般name和value通過編碼)。算法
Cookie主要由如下幾個字段組成:瀏覽器
Cookie: [name][value][domain][path][expires][httpOnly][secure]
一般經過JS設置Cookie爲如下形式。固然,最好的方式是經過一個函數來設置。安全
document.cookie = 'name=kk; domain=localhost; path=/; expires= Mon Nov 06 2017 01:32:07 GMT+0800 (CST)'
name, value: 是Cookie的名稱和值。Cookie的name和value必須通過url編碼。在JS中能夠經過window.encodeURIComponent
方法來對name和value進行編碼。同時,在寫cookie的時候要注意,cookie的名稱是不區分大小寫的。因此myCookie和MyCookie被認爲是同一個cookie。可是在實際開發過程當中,最好區分大小寫。服務器
domain: Cookie對於哪一個域是有效的。因此向該域發出的請求都會包含Cookie信息。設置Cookie時,若是不指定Cookie的值,默認就是本域名。如我在本地經過Node.js起服務器時,Cookie的domain爲domain=localhost
。cookie
子域能夠獲取當前域(父域)的cookie,可是當前域(父域)不能獲取子域的cookie。好比說,當前域爲a.com,在a.com設置了cookie。那麼其子域b.a.com能夠獲取a.com的cookie。可是若是在b.a.com設置的cookie,在a.com域名下不能獲取到b.a.com下的cookie。session
path: 對於指定域中的那個路徑,應該向服務器發送cookie。默認狀況下,若是不設置Cookie的path時,默認路徑爲/。好比說,在a.com/profile路徑下設置的cookie,那麼在訪問此路徑的時候纔會發送cookie,在訪問a.com時不會發送cookie。dom
若是須要跨路徑獲取Cookie值,可使用隱藏的iframe實現,可是必須是同源的。
expires:表示Cookie什麼時候被刪除的時間戳。這個時間戳是GMT格式的日期(Wdy, DD-Mon-YYYY HH:MM:SS GMT)。若是設置成之前的時間,則Cookie會被當即刪除。若是設置的是未來的某個時間,那麼即便關閉瀏覽器,cookie仍然保持在用戶的電腦上。expires字段的設置與否,會把Cookie分爲兩種:本地(持久化)Cookie和內存(非持久化)Cookie。在介紹分類的時候再細說。
httpOnly: 顧名思義,httpOnly是指在HTTP層面上傳輸的Cookie。當服務端對Cookie消息設置了httpOnly標誌以後,客戶端腳本就沒法經過document.cookie
的方式讀寫cookie。可以讀取意味着能夠獲取Cookie,可以寫入Cookie意味着能夠篡改Cookie。所以,對重要的Cookie消息設置httpOnly可以有效防護XSS攻擊獲取Cookie。
secure: secure代表設置了secure字段的Cookie只能在HTTPS上進行安全數據傳輸。若是請求是HTTP的,就不會帶上這個Cookie。這裏要留心一點的是,服務端設置cookie下的secure字段,它並非以名稱-值對的形式的。而是單單一個secure單詞。例如,Cookie信息只能發送給https://keith.com,而http://keith.com的請求則不能發送Cookie。
如如下響應頭,其餘字段是名稱-值對的形式,而secure是一個單詞。 HTTP/1.1 200 OK Content-Type: text/html Set-Cookie: name=keith; domain=localhost; path=/; exipres=Mon, 08-June-18 07:10:24 GMT; secure
可是,有一個很特別的是設置了secure字段的Cookie能夠被讀寫。所以,通常狀況下,若是隻容許HTTPS獲取數據,服務端能夠一塊兒配置secure + httpOnly字段,這樣就可以保證HTTPS傳輸,而且避免了Cookie被讀寫的風險。
大多數瀏覽器Cookie默認大小爲4kb。超過的部分會被截斷掉。
根據Cookie中的expires字段,能夠將Cookie分爲本地(持久化)Cookie和內存(非持久化)Cookie。
當expires沒有設置時,實際上就至關於一個內存Cookie。瀏覽器關閉以後就消失了。同時,在當前瀏覽器下,打開多個頁面仍然能夠訪問到Cookie消息。也就是說,若是瀏覽器不關掉的狀況下都會發送Cookie。
當expires設置一個將來的時間,那麼就是一個本地Cookie。此時會將Cookie存入到操做系統本地,待過時時間到了纔會消失。
所以根據expires字段,能夠利用Cookie作用戶登陸認證、購物車信息存儲等功能。
當登陸一個網站的時候。
在購物場景中。
Cookie缺點:
1.Cookie的大小限制在4kb左右。對於複雜的存儲來講是不夠的
2.Cookie會被附加在每一個HTTP請求中,因此會增長HTTP請求大小
3.因爲Cookie都是在HTTP請求中明文傳遞的,會有安全性問題(除非使用HTTPS)
sessionStorage和localStorage對象都是繼承自Storage原型對象的。在Storage對象中存在如下方法
clear(): 清除全部storage setItem(name, value): 設置storage, 也能夠經過點語法或者方括號設置 getItem(name): 獲取name對應的value值, 也能夠經過點語法或者方括號獲取 removeItem(name): 刪除單個storage。 也能夠經過delete操做符刪除 key(index): 獲取index位置處的name
sessionStorage存儲大小爲5MB(大多數瀏覽器)。它屬於一種非持久化數據,在瀏覽器關掉時數據就消失了。同時,在瀏覽器未關閉,而從新開一個頁面(切換了路徑),也是沒法訪問到sessionStorage的。所以在多頁面應用時有限制。可使用localStorage來代替。
因爲sessionStorage是對象,因此能夠經過for-in語句或者結合length屬性來遍歷每一個storage值,對於localStorage對象來講也是適用的。
// 方法一 for (let key in window.sessionStorage) { let value = window.sessionStorage[key] console.log(`${key}=${value}`) } // 方法二 for (let i = 0; i < window.sessionStorage.length; i++) { let key = window.sessionStorage.key(i) let value = window.sessionStorage[key] console.log(`${key}=${value}`) }
localStorage的存儲大小也爲5MB(大多數瀏覽器)。localStorage會存儲在本地操做系統的文件中。在數據時效性上,localStorage並不會想cookie那樣能夠設置數據的過時時間。也就是說,只要用戶不主動刪除localStorage,localStorage存儲的數據將會永久存在。
注意,localStorage沒法跨瀏覽器存在。
這樣介紹一個看,localStorage即比Cookie擁有更大的數據存儲空間,並且數據也是持久化的,不會隨着網頁的關閉而消失,好像能夠代替Cookie來作用戶身份驗證。
實際上是不能的。咱們知道,一般能夠經過XSS漏洞來獲取到Cookie,而後用這個Cookie進行身份驗證登陸。可是爲了防止經過XSS獲取到Cookie數據,服務器能夠配置httpOnly來保護Cookie,禁止瀏覽器經過腳本document.cookie
獲取到Cookie。而localStorage存儲沒有對XSS攻擊有任何的防護機制,一旦出現XSS漏洞,那麼存儲在localStorage裏的數據(如重要的用戶名、密碼)就極容易被獲取到。所以重要的信息不要存儲在storage對象中。
在改變sessionStorage對象或者localStorage對象以後,就會觸發Storage事件。也就是說,當刪除、修改、設置storage時,都會調用Storage事件。Storage事件的事件對象存在如下屬性。
domain: 發生變化的存儲的域名
key: 設置或刪除的鍵名
newValue: 若是是設置值,則對應一個新值;若是是刪除值,則是null
oldValue: 鍵值被修改前的值
document.addEventListener('storage', (e) => { console.log(e.domain) console.log(e.key) console.log(e.newValue) console.log(e.oldValue) }, false)
這個目前我暫時尚未用過....先佔位,用過以後再回來填坑