前端三種本地儲存方式
前言
網路早期最大的問題之一是如何管理狀態。簡而言之,伺服器無法知道兩個請求是否來自同一個瀏覽器。當時最簡單的方法是在請求時,在頁面中插入一些引數,並在下一個請求中傳回引數。這需要使用包含引數的隱藏的表單,或者作為URL引數的一部分傳遞。這兩個解決方案都手動操作,容易出錯。cookie出現來解決這個問題。
作用
cookie是純文字,沒有可執行程式碼。儲存資料,當用戶訪問了某個網站(網頁)的時候,我們就可以通過cookie來向訪問者電腦上儲存資料,或者某些網站為了辨別使用者身份、進行session跟蹤而儲存在使用者本地終端上的資料(通常經過加密)
如何工作
當網頁要發http請求時,瀏覽器會先檢查是否有相應的cookie,有則自動新增在request header中的cookie欄位中。這些是瀏覽器自動幫我們做的,而且每一次http請求瀏覽器都會自動幫我們做。這個特點很重要,因為這關係到“什麼樣的資料適合儲存在cookie中”。
儲存在cookie中的資料,每次都會被瀏覽器自動放在http請求中,如果這些資料並不是每個請求都需要發給服務端的資料,瀏覽器這設定自動處理無疑增加了網路開銷;但如果這些資料是每個請求都需要發給服務端的資料(比如身份認證資訊),瀏覽器這設定自動處理就大大免去了重複新增操作。所以對於那種設定“每次請求都要攜帶的資訊(最典型的就是身份認證資訊)”就特別適合放在cookie中,其他型別的資料就不適合了。
特徵-
不同的瀏覽器存放的cookie位置不一樣,也是不能通用的。
-
cookie的儲存是以域名形式進行區分的,不同的域下儲存的cookie是獨立的。
-
我們可以設定cookie生效的域(當前設定cookie所在域的子域),也就是說,我們能夠操作的cookie是當前域以及當前域下的所有子域
-
一個域名下存放的cookie的個數是有限制的,不同的瀏覽器存放的個數不一樣,一般為20個。
-
每個cookie存放的內容大小也是有限制的,不同的瀏覽器存放大小不一樣,一般為4KB。
-
cookie也可以設定過期的時間,預設是會話結束的時候,當時間到期自動銷燬
客戶端設定
document.cookie = '名字=值';
document.cookie = 'username=cfangxu;domain=baike.baidu.com'//並且設定了生效域
注意:客戶端可以設定cookie 的下列選項:expires、domain、path、secure(有條件:只有在https協議的網頁中,客戶端設定secure型別的 cookie 才能成功),但無法設定HttpOnly選項。
伺服器端設定
不管你是請求一個資原始檔(如 html/js/css/圖片),還是傳送一個ajax請求,服務端都會返回response。而response header中有一項叫set-cookie,是服務端專門用來設定cookie的。
Set-Cookie 訊息頭是一個字串,其格式如下(中括號中的部分是可選的):
Set-Cookie: value[; expires=date][; domain=domain][; path=path][; secure]
注意:一個set-Cookie欄位只能設定一個cookie,當你要想設定多個 cookie,需要新增同樣多的set-Cookie欄位。
服務端可以設定cookie 的所有選項:expires、domain、path、secure、HttpOnly
通過 Set-Cookie 指定的這些可選項只會在瀏覽器端使用,而不會被髮送至伺服器端。
讀取 我們通過document.cookie來獲取當前網站下的cookie的時候,得到的字串形式的值,它包含了當前網站下所有的cookie(為避免跨域指令碼(xss)攻擊,這個方法只能獲取非 HttpOnly 型別的cookie)。它會把所有的cookie通過一個分號+空格的形式串聯起來,例如username=chenfangxu;job=coding
修改cookie
要想修改一個cookie,只需要重新賦值就行,舊的值會被新的值覆蓋。但要注意一點,在設定新cookie時,path/domain這幾個選項一定要舊cookie 保持一樣。否則不會修改舊值,而是添加了一個新的 cookie。
刪除
把要刪除的cookie的過期時間設定成已過去的時間,path/domain/這幾個選項一定要舊cookie 保持一樣。注意 如果只設置一個值,那麼算cookie中的value; 設定的兩個cookie,key值如果設定的相同,下面的也會把上面的覆蓋。
cookie的屬性(可選項)
過期時間如果我們想長時間存放一個cookie。需要在設定這個cookie的時候同時給他設定一個過期的時間。如果不設定,cookie預設是臨時儲存的,當瀏覽器關閉程序的時候自動銷燬。
注意:document.cookie = '名稱=值;expires=' + GMT(格林威治時間)格式的日期型字串;
一般設定天數: newDate().setDate(oDate.getDate()+5);
比當前時間多5天
一個設定cookie時效性的例子:
function setCookie(c_name, value, expiredays){
var exdate=new Date();
exdate.setDate(exdate.getDate() + expiredays);
document.cookie=c_name+ "=" + escape(value) + ((expiredays==null) ? "" : ";expires="+exdate.toGMTString())
}
使用方法;
setcookie('username','zxy',30);
expires 是 http/1.0協議中的選項,在新的http/1.1協議中expires已經由 max-age 選項代替,兩者的作用都是限制cookie 的有效時間。expires的值是一個時間點(cookie失效時刻= expires),而max-age 的值是一個以秒為單位時間段(cookie失效時刻=
建立時刻+ max-age)。另外,max-age 的預設值是 -1(即有效期為 session );max-age有三種可能值:負數、0、正數。
-
負數:有效期session;
-
0:刪除cookie;
-
正數:有效期為建立時刻+ max-age
瀏覽器會把 domain 的值與請求的域名做一個尾部比較(即從字串的尾部開始比較),並將匹配的 cookie 傳送至伺服器
document.cookie = "username=cfangxu;path=/;domain=qq.com"
如上:“www.qq.com" 與 "sports.qq.com"
公用一個關聯的域名"qq.com",我們如果想讓 "sports.qq.com" 下的cookie被 "www.qq.com" 訪問,我們就需要用到 cookie 的domain屬性,並且需要把path屬性設定為 "/"。服務端設定 Set-Cookie:username=zxy;path=/;domain=qq.com; 注:一定的是同域之間的訪問,不能把domain的值設定成非主域的域名。 cookie的路徑概念(path選項) cookie 一般都是由於使用者訪問頁面而被建立的,可是並不是只有在建立 cookie 的頁面才可以訪問這個 cookie。 因為安全方面的考慮,預設情況下,只有與建立 cookie 的頁面在同一個目錄或子目錄下的網頁才可以訪問。即path屬性可以為伺服器特定文件指定cookie,這個屬性設定的url且帶有這個字首的url路徑都是有效的。
客戶端設定
最常用的例子就是讓 cookie 在根目錄下,這樣不管是哪個子頁面建立的 cookie,所有的頁面都可以訪問到了。
document.cookie="username=zxy;path=/"
服務端設定
Set-Cookie:name=zxy;path=/blog'
如上設定:path 選項值會與 /blog,/blogrool 等等相匹配;任何以 /blog 開頭的選項都是合法的。需要注意的是,只有在 domain 選項核實完畢之後才會對 path 屬性進行比較。path 屬性的預設值是傳送 Set-Cookie 訊息頭所對應的 URL 中的 path 部分。
domain和path總結
domain是域名,path是路徑,兩者加起來就構成了 URL,domain和path一起來限制 cookie 能被哪些 URL 訪問。
所以domain和path2個選項共同決定了cookie何時被瀏覽器自動新增到請求頭部中傳送出去。如果沒有設定這兩個選項,則會使用預設值。domain的預設值為設定該cookie的網頁所在的域名,path預設值為設定該cookie的網頁所在的目錄。
cookie的安全性(secure選項)
通常 cookie 資訊都是使用HTTP連線傳遞資料,這種傳遞方式很容易被檢視,所以 cookie 儲存的資訊容易被竊取。假如 cookie 中所傳遞的內容比較重要,那麼就要求使用加密的資料傳輸。
secure選項用來設定cookie只在確保安全的請求中才會發送。當請求是HTTPS或者其他安全協議時,包含 secure 選項的 cookie 才能被髮送至伺服器。
document.cookie="username=zxy;secure'
把cookie設定為secure,只保證 cookie 與伺服器之間的資料傳輸過程加密,而儲存在本地的 cookie檔案並不加密。就算設定了secure 屬性也並不代表他人不能看到你機器本地儲存的 cookie 資訊。機密且敏感的資訊絕不應該在 cookie 中儲存或傳輸,因為 cookie 的整個機制原本都是不安全的。
注意:如果想在客戶端即網頁中通過 js 去設定secure型別的 cookie,必須保證網頁是https協議的。在http協議的網頁中是無法設定secure型別cookie的。
httpOnly
這個選項用來設定cookie是否能通過 js 去訪問。預設情況下,cookie不會帶httpOnly選項(即為空),所以預設情況下,客戶端是可以通過js程式碼去訪問(包括讀取、修改、刪除等)這個cookie的。當cookie帶httpOnly選項時,客戶端則無法通過js程式碼去訪問(包括讀取、修改、刪除等)這個cookie。
在客戶端是不能通過js程式碼去設定一個httpOnly型別的cookie的,這種型別的cookie只能通過服務端來設定。
cookie的編碼
cookie其實是個字串,但這個字串中等號、分號、空格被當做了特殊符號。所以當cookie的
key 和 value 中含有這3個特殊字元時,需要對其進行額外編碼,一般會用escape進行編碼,讀取時用unescape進行解碼;當然也可以用encodeURIComponent/decodeURIComponent或者encodeURI/decodeURI,檢視關於編碼的介紹
第三方cookie
通常cookie的域和瀏覽器地址的域匹配,這被稱為第一方cookie。那麼第三方cookie就是cookie的域和位址列中的域不匹配,這種cookie通常被用在第三方廣告網站。為了跟蹤使用者的瀏覽記錄,並且根據收集的使用者的瀏覽習慣,給使用者推送相關的廣告。
關於第三方cookie和cookie的安全問題可以檢視
HTML5新方法,不過IE8及以上瀏覽器都相容。
特點:
-
生命週期:持久化的本地儲存,除非主動刪除資料,否則資料是永遠不會過期的。
-
儲存的資訊在同一域中是共享的。
-
當本頁操作(新增、修改、刪除)了localStorage的時候,本頁面不會觸發storage事件,但是別的頁面會觸發storage事件。
-
大小:據說是5M(跟瀏覽器廠商有關係)
-
在非IE下的瀏覽中可以本地開啟。IE瀏覽器要在伺服器中開啟。
-
localStorage本質上是對字串的讀取,如果儲存內容多的話會消耗記憶體空間,會導致頁面變卡
-
localStorage受同源策略的限制
lacalStorage.setItem('username','zxy');
獲取
localStorage.getItem('username');
刪除
localStorage.remove('username');
也可以一次清除所有儲存
localStorage.clear();
storage事件
當storage發生改變的時候觸發。
注意:當前頁面對storage的操作會觸發其他頁面的storage事件。
事件的回撥函式中有一個引數event,是一個StorageEvent物件,提供了一些實用的屬性,如下表:
Property | Type | Description |
---|---|---|
key | String | The named key that was added, removed, or moddified |
oldValue | Any | The previous value(now overwritten), or null if a new item was added |
newValue | Any | The new value, or null if an item was added |
url/uri | String | The page that called the method that triggered this change |
其實跟localStorage差不多,也是本地儲存,會話本地儲存
特點:
用於本地儲存一個會話(session)中的資料,這些資料只有在同一個會話中的頁面才能訪問並且當會話結束後資料也隨之銷燬。因此sessionStorage不是一種持久化的本地儲存,僅僅是會話級別的儲存。也就是說只要這個瀏覽器視窗沒有關閉,即使重新整理頁面或進入同源另一頁面,資料仍然存在。關閉視窗後,sessionStorage即被銷燬,或者在新視窗開啟同源的另一個頁面,sessionStorage也是沒有的。
cookie,localStorage,sessionStorage區別
相同:在本地(瀏覽器端)儲存資料。
不同:
-
localStorage只要在相同的協議、相同的主機名、相同的埠下,就能讀取/修改到同一份localStorage資料。
-
sessionStorage比localStorage更嚴苛一點,除了協議、主機名、埠外,還要求在同一視窗(也就是瀏覽器的標籤頁)下。
-
localStorage是永久儲存,除非手動刪除。
-
sessionStorage當會話結束(當前頁面關閉的時候,自動銷燬)
-
cookie的資料會在每一次傳送http請求的時候,同時傳送給伺服器而localStorage、sessionStorage不會。