1. 程式人生 > >瀏覽器端資料儲存之Cookie、localStorage、sessionStorage

瀏覽器端資料儲存之Cookie、localStorage、sessionStorage

Cookie、localStorage、sessionStorage都是儲存在瀏覽器端會話資料,接下來分別詳細介紹三種機制。
一、cookie

1、什麼是cookie

cookie 是儲存於訪問者的計算機中的變數。每當同一臺計算機通過瀏覽器請求某個頁面時,就會發送這個 cookie。cookie的作用是儲存客戶端上使用者的資訊包括登陸資訊、偏好設定或者其他資料。在我一篇HTTP協議的文章中提到過Cookie,由於HTTP協議是一種無狀態協議,每一次請求之間沒有都是獨立的,那麼要儲存使用者的會話資訊的話,就要在每一次HTTP請求過程中附帶上Cookie傳送給伺服器。下面是我用fiddler獲取www.qq.com的請求資料:

GET http://www.qq.com/ HTTP/1.1
Host: www.qq.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:51.0) Gecko/20100101 Firefox/51.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://e.firefoxchina
.cn/?cachebust=20160321 Cookie:pt2gguin=o1137567854;ptcz=7d097f461558c3395939a07e244fef634e4f53ff88165b697835e925ffbf6df8; tvfe_boss_uuid=144c3d24ad91e75b; pgv_pvid=1738290900; o_cookie=1137567854; pgv_pvi=6978680832; RK=t12WR4aufe; ts_refer=e.firefoxchina.cn/; ts_uid=1209845192; pac_uid=1_1137567854 Connection:
keep-alive Upgrade-Insecure-Requests: 1

2、cookie的構成

名稱:唯一確定一個cookie的名稱。而且不區分大小寫;經過URL編碼。
值:儲存在cookie的字串。經過URL編碼。如上面的ptcz=7d097f461558c3395939a07e244fef634e4f53ff88165b697835e925ffbf6df8;
域名:說明cookie在哪個域名下有效
路徑:指定域中哪個路徑對伺服器傳送cookie。比如指定http://www.qq.com/s/,下才能訪問cookie,那麼就不會向http://www.qq.com/傳送cookie。
失效時間:指定cookie失效的日期。接受的是GMT格式的時間,可以用toGMTSting函式將其他時間格式轉換為GMT格式的時間。如果設定了一個以前的時間。那麼這個cookie立刻消失。
安全標誌:直接指定為secure.表示只有在SSL連線時候才傳送給伺服器。也就是在HTTPS協議的時候才會傳送cookie到伺服器上。來看一條完整的cookie

Set-Cookie: IPLOC=CN4403; expires=Tue, 13-Mar-18 07:54:07 GMT; domain=.sogou.com; path=/

這是抓取百度的一條響應頭資訊裡面的cookie。可以看到
名稱: IPLOC,
值: CN4403。
失效時間為: 13-Mar-18 07:54:07 GMT。
域名為:.sogou.com
路徑: 當前路徑,也就是在整個域名下
安全標誌: 沒有
注意:
i:儲存規則
一條cookie資訊要遵循比較嚴格的模式,這是因為js下面所有的cookie值是儲存在document.cookie下面的一個字串裡面。這樣的話對於我們存取cookie值是非常不便的。為了能更好的存取cookie我們要有一種規定的格式。設定cookie的時候格式按照HTTP響應中set-cookie中順序和格式。每一段資訊都使用分號加上空格的方式分隔。等會再構造存取cookie時會詳細講解。
ii:哪些資料傳送到伺服器
只有名稱和值會發送到伺服器。其他屬性只是伺服器給瀏覽器的一個提示。

3、瀏覽器對cookie的限制
為了限制cookie不會被惡意用,以及不會佔用太多磁碟空間,而且因為每一次請求的時候都要帶上cookie,太多cookie會影響請求的效能。如此不同的瀏覽器會對cookie的數量和空間有響應的限制措施:
這裡寫圖片描述

4、js中的cookie
js中cookie是一種不太友好的處理方式。它將所有的cookie存放在了docunment.cookie的字串裡面。比如:

name1=value1;name2=value2;name3=value3

而且js在設定一個cookie值得時候是這樣的:

document.cookie="name=周運金";

這樣並不會將之前的cookie值覆蓋掉,這點需要理解。而且在設定cookie的時候只有名稱和值是必須的。預設的過期時間實在你瀏覽器會話結束時間。上面提到過名稱和值都必須經過URL編碼,但是這裡正好不需要進行URL編碼(只有字母和數字[0-9a-zA-Z]、一些特殊符號”$-_.+!*’(),”[不包括雙引號]、以及某些保留字,才可以不經過編碼直接用於URL)
js採用encodeURComponent(string)函式進行編碼。
比如設定一條cookie可以採用:

document.cookie=encodeURComponent("name")+"="+encodeURComponent("周運金")+"; domain=.yjblog.cn; path=/; expires="+(new Date("May 1,2017")).toGMTString();

5、JS中存取cookie的類
該類中封裝了cookie的三種操作:讀取、寫入、刪除;

var CookieUtil = {
  // 設定cookie
  set : function (name, value, expires, domain, path, secure) {
    var cookieText = "";           //要設定的cookie字串
    cookieText += encodeURIComponent(name) + "=" + encodeURIComponent(value);      //名稱和值是必選引數,下面的可選
    if (expires instanceof Date) { //檢查時間是否標準格式
      cookieText += "; expires=" + expires.toGMTString();
    }
    if (path) {
      cookieText += "; path=" + path;
    }
    if (domain) {
      cookieText += "; domain=" + domain;
    }
    if (secure) {
      cookieText += "; secure";
    }
    document.cookie = cookieText;
  },
  // name=value; expires=expiration_time; path=domain_path; domain=domain_name; secure
  // 獲取cookie
  get : function (name) {
    var cookieName = encodeURIComponent(name) + "=",
      cookieStart = document.cookie.indexOf(cookieName),
      cookieValue = "";     //記得URL解碼
    if (cookieStart > -1) {
      var cookieEnd = document.cookie.indexOf (";", cookieStart);      //以;為標誌,記得從cookieStart位置開始查詢字串
      if (cookieEnd == -1) {//如果沒有;說明到字串尾部了
        cookieEnd = document.cookie.length;
      }
      cookieValue = decodeURIComponent(document.cookie.substring(cookieStart + cookieName.length, cookieEnd));//注意這裡等號已經被跳過了,cookieStart + cookieName.length已經是從值得第一個字母開始了
    }
    return cookieValue; 
  },
  // 刪除cookie
  unset : function (name, domain, path, secure) {
    this.set(name, "", Date(0), domain, path, secure);
  }  //cookie的刪除其實是將時間設定為過期
};
//設定cookie
CookieUtil.set("name","周運金");
CookieUtil.set("names","李佳家",new Date("May 1,2017"),"/s/",".yjblog.cn","secure"); 

//讀取cookie
alert(CookieUtil.get("name"));
alert(CookieUtil.get("names"));

//刪除cookie
CookieUtil.unset("name");
CookieUtil.unset("names");

//設定安全cookie
CookieUtil.set("names","李佳家",null,null,null,"secure"); 
//中間的引數用null填充,但是不能空缺

6、Cookie注意事項
i、儲存太多cookie影響HTTP請求的效能
由於所有的cookie又會有瀏覽器作為請求頭髮送,所以cookie儲存大量的詩句會影響到請求的效能,浪費頻寬。cookie資訊越多,請求的時間將越長,這是我們應該避免的。儘管瀏覽器對cookie做了限制,但是我們開發者應該在cookie少儲存資訊。(這就是需要Web Storage)
ii、安全性
由於HTTP採用的是明文模式,從我之前的關於通過xss攻擊獲取cookie
的文章可以看出,cookie的資訊很容易被獲取。所以對於一些敏感的資料比如使用者賬號密碼、信用卡密碼等都不要存放在cookie裡面。
iii、資料丟失
當超過cookie限制的時候,有些瀏覽器如火狐會隨機刪除掉一些cookie以騰出空間給新的cookie,IE和Opera智慧一點,會刪除比較少用的cookie。
iiii、有些狀態不可能儲存在客戶端
為了防止重複提交表單,我們需要在伺服器端儲存一個計數器。如果我們把這個計數器儲存在客戶端,那麼它起不到任何作用。(這個就需要session來做了)

針對cookie大小限制以及資料量大會浪費頻寬,HTML5標準出現了Web Storage克服cookie帶來的限制。當資料被嚴格控制在客戶端時,無需持續低將資料發回伺服器。它的出現有兩個主要的目的
1、提供一種在cookie之外儲存會話資料的途徑。
2、提供一種儲存大量可以跨會話存在的資料機制。
主要有兩種型別:sessionStorage、localStorage

二、sessionStorage與localStorage
1、什麼是sessionStorage與localStorage?
從上一段中也可以大概猜出什麼是sessionStorage/localStorage了。sessionStorage是類似於cookie可以將資料儲存在瀏覽器端的一個物件。但是它不像cookie一樣被髮送到伺服器,也因為這樣sessionStorage有更大的容量,最大可以達到8M,適合儲存比較大的資料。
2、sessionStorage的用法(包括localStorage的用法)
setItem儲存value

用途:將value儲存到key欄位
用法:.setItem( key, value)
程式碼示例:

sessionStorage.setItem("name", "周運金");  
localStorage.setItem("name", "李佳家");

getItem獲取value

用途:獲取指定key本地儲存的值
用法:.getItem(key)
程式碼示例:

var value = sessionStorage.getItem("name"); 
var site = localStorage.getItem("name");

removeItem刪除key

用途:刪除指定key本地儲存的值
用法:.removeItem(key)
程式碼示例:

sessionStorage.removeItem("name");  localStorage.removeItem("name");

clear清除所有的key/value

用途:清除所有的key/value
用法:.clear()
程式碼示例:

sessionStorage.clear(); 
localStorage.clear();

其他操作方法:點操作和[]

web Storage不但可以用自身的setItem,getItem等方便存取,也可以像普通物件一樣用點(.)操作符,及[]的方式進行資料儲存,像如下的程式碼:

var storage = window.localStorage;
storage.name= "周運金";
console.log(storage.name);
console.log(storage["name"]);

localStorage和sessionStorage的key和length屬性實現遍歷

sessionStorage和localStorage提供的key()和length可以方便的實現儲存的資料遍歷,例如下面的程式碼:

var storage = window.localStorage;
for (var i=0, len = storage.length; i  <  len; i++){ 
var key = storage.key(i);           //先獲取鍵名
var value = storage.getItem(key);   //獲取鍵值 
    console.log(key + "=" + value); 
 }

甚至還可以用for in遍歷

for(var key in sessionStorage){
    var value =sessionStorage.getItem(key);
    alert(key+"="+value);
}

每次迴圈key會向指標一樣指向sessionStorage的下一個鍵名。
3、storage事件

if(window.addEventListener){             window.addEventListener("storage",handle_storage,false);
 }
else if(window.attachEvent){    window.attachEvent("onstorage",handle_storage); 
} 
function handle_storage(e){ 
    if(!e){
         e=window.event;
    }   
 }

3、二者的區別
i、作用域
相同瀏覽器的不同頁面間可以共享相同的 localStorage(頁面屬於相同域名和埠),但是sessionStorage只能在同源(相同域名相同埠)同窗口訪問,但是當sessionStorage在同一視窗下轉到同源頁面還是可以訪問的,因為這時候還是同源同窗口,不要單純理解為兩個不同的頁面之間不能訪問相同sessionStorage。比如你在A網頁設定了一個sessionStorage的值,然後你同時在新的視窗下開啟B網頁,這時候你嘗試在B網頁得到A網頁設定的sessionStorage是不可以的,但是當你在A網頁跳轉到B網頁的時候,這時候你會發現B網頁可以訪問A網頁中的sessionStorage。所以sessionStorage針對的是同源同窗口,不是同源同頁面。
ii、生命週期
localStorage生命週期是永久,這意味著除非使用者自己清除localStorage資訊或者使用者清除瀏覽器快取,否則這些資訊將永遠存在。
sessionStorage生命週期為當前視窗或標籤頁,一旦視窗或標籤頁被永久關閉了,那麼所有通過sessionStorage儲存的資料也就被清空了。

總結:
cookie與sessionStorage、localStorage的區別
1、cookie可以在瀏覽器端與伺服器端之間通訊,是伺服器端獲取使用者資訊、保持一種持久客戶端狀態的關鍵。而sessionStorage、localStorage
雖然也可以儲存會話資料,但是不能與伺服器端進行資訊交換。
2、cookie的容量比較小。而sessionStorage、localStorage有較大的容量
3、試用的瀏覽器範圍不同。由於sessionStorage與localStorage是HTML5標準推出的,所以在IE7以及IE7以下的版本不適用。替代方案是採用IE的userData.(有興趣可以瞭解一下)
最後:sessionStorage、localStorage的出現正好彌補了了cookie由於大小限制帶來的問題,三者相輔相成為瀏覽器儲存資料提供了更好的解決方案。