cookie、localStorage、sessionStroage介紹及其對比

1. cookie

cookie最初是設計給服務端用的。若是客戶端有cookie,則每次請求都會發給服務端。下面來具體看一下這個機制。node

1.1 cookie 的設置

就像上面說的,cookie最初是設計給服務端使用的。cookie就像服務端給這個客戶端加的一個標籤,當客戶端再次請求時,會帶着這個標籤,那麼服務器就能經過攜帶的cookie知道當前的客戶端是誰了。api

cookie的設置過程大致以下:跨域

  1. 客戶端請求服務端,服務端看到客戶端是新來的,就用回覆頭裏的set-cookie設置一個cookie給這個客戶端返回,做爲標記,例如這個標籤是 Joey
  2. 客戶端收到cookie,在之後向服務端再發請求的時候會在頭部的cookie字段加上服務端在上一步中發來的cookie,即 Joey
  3. 服務端收到了cookie: Joey, 就知道了這個用戶是Joey, 而後就能夠作進一步的操做了

1.2 cookie 的用處

Cookie主要用於如下三個方面:數組

  1. 會話狀態管理(如用戶登陸狀態、購物車、遊戲分數或其它須要記錄的信息)瀏覽器

  2. 個性化設置(如用戶自定義設置、主題等)緩存

  3. 瀏覽器行爲跟蹤(如跟蹤分析用戶行爲等)安全

1.3 安全問題--cookie 是不可信的

cookie 是能夠被修改的,客戶端和服務端均可以對已經設置的cookie進行修改。服務器

在1.1部分的cookie設置過程當中可知,若是客戶端將原本是 Joey的 cookie 改爲 Ross,那麼服務器就會認爲如今發請求的客戶端是 Ross,可能會給客戶端 Joey 返回原本屬於 Ross 的內容。這確定是不該該的。cookie

因此說, cookie 是不可信的。網絡

1.4 cookie 的體積限制

客戶端在得到服務端返回的 cookie 後,在之後再給服務器發請求時,不管服務端是否是想要 cookie, 都會放在請求裏發過去。

咱們知道,網絡請求是很是耗時間的,若是cookie過大,每次請求服務器時都會在 header 中帶上 cookie ,則網絡請求時間會過長。

因此大多數瀏覽器都對每一個域的cookie數量和大小有限制,每一個瀏覽器對cookie數量的限制不相同,但對總大小的限制大都是4096B。

若是新加入的cookie要超過了瀏覽器的最大數量限制,會刪除較早的 cookie 以騰出空間。不一樣瀏覽器的刪除策略不一樣,有的會刪除最近最少使用的 cookie,例如 IE和Opera;有些彷佛會隨機選擇一個來刪除,例如 Firefox...

若是新的加入新的 cookie 以後全部 cookie 的總大小超過限制,則新的 cookie 不會設置成功, 會被丟棄。

因此,不要設置太多 cookie, 以避免出現意料不到的事情。

1.5 cookie 的構成

cookie由如下幾個字段組成:

  1. name:名稱,惟一值,用來惟一識別cookie,不分大小寫。必須通過 URL 編碼
  2. value:值,對應於名稱,必須通過 URL 編碼
  3. domain:域,設置cookie對於哪一個域是有效的,都向這個域裏發cookie。例如domain值爲www.baidu.com,則全部發向這個網址的請求,都會發這個cookie
  4. path:路徑,指定域裏的路徑能夠接受這個cookie,例如百度下的/search路徑:www.baidu.com/search
  5. expires:過時時間,表示這個cookie何時應該被刪除,這是個日期格式的。若是沒有定義,cookie會在對話結束時過時。若是想讓一個cookie立刻過時,則能夠將這個值設置成過去的時間。
  6. max-age:過時倒計時,以秒爲單位。若是設置成0,則這個cookie馬上失效,設置負數時不會產生cookie文件
  7. secure :設置該 cookie 只經過https協議傳輸,這不是鍵值對,是個標記,寫上就表明設置爲只在使用 https 傳輸。從 Chrome 52 和 Firefox 52 開始,不安全的站點使用http協議的站點沒法使用Cookie的 Secure 標記
  8. http-only:設置不容許在瀏覽器端用 JavaScript 獲取到 cookie。這也不是個鍵值對,是個標記,寫上就表明生效。能夠用來防止跨域腳本(XSS )攻擊
  9. samesite:要求cookie在跨站請求時不會被髮送,防止跨站請求僞造(CSRF)的特性,可取值

其中除name: value爲必須以外,其他都是可選項。

1.6 在客戶端用 JavaScript 操做 cookie

在客戶端使用 JavaScript 對 cookie 的操做能夠分爲兩類,分別是讀取 cookie 和 設置 cookie,下面分別進行討論。

BOM 的提供的操做 cookie 的 api 看起來有些難用。

1.6.1 讀取 cookie

使用 document.cookie 便可得到該頁面中全部的 cookie,例如,咱們來看看百度學術給我設置了什麼cookie。打開http://xueshu.baidu.com/。按F12,打開上部分的 Application 選項卡,而後打開左側的 cookies。

百度學術在個人電腦裏保存的cookie如圖:

而後在命令臺上經過 document.cookie 來獲取頁面裏的 cookie:

// 獲取 cookie, 獲得的是全部 cookie 組成的字符串
let cookies = document.cookie;
// 提取出全部的 cookie 到數組中
let cookieArray = cookies.split(';');
// 用 console.table 輸出cookie數組,這樣比較清晰
console.table(cookieArray);
複製代碼

結果以下:

能夠看到經過 document.cookie 獲取的 cookie 的 name 和 value 與瀏覽器工具獲得的相同。

以圖中第一個cookie爲例,cookie 名爲 PSTM , value 是1563885xxx,域名是 .baidu.com,過時時間是2087年8月10號,其餘屬性都取默認值。

1.6.2 設置 cookie

給 document.cookie 賦一個新的 cookie 字符串能夠設置一個新的 cookie 了。

以MDN爲例,在這個網站域名下設置一個本身的cookie,配置以下:

  • cookie 名爲 username,
  • cookie 值爲 test,
  • domain爲 .mozilla.org
  • path爲 /

其餘選項不設置,也就是取默認值。

設置以前的 cookie 爲:

設置:

let name = 'username',
	value = 'test',
	domain = '.mozilla.org',
	path = '/';

var myCookie = encodeURIComponent(name) + '=' + encodeURIComponent(value) + ';domain=' + domain + ';path=' + path;

document.cookie = myCookie;
複製代碼

結果以下:

能夠看到 cookie 設置成功了。

1.7 服務端設置 cookie 發送給客戶端

因爲不一樣服務端程序的在響應報文的頭部設置 set-cookie 操做的具體代碼不一樣,這裏以 node.js 的 koa 框架爲例。

先起一個極簡的 server,而後對於訪問者返回的報文的 header 都設置 set-cookie 頭部:

const Koa = require('koa');
const app = new Koa();

app.use(async ctx => {
  ctx.cookies.set('koa_cookie_name', 'koa_cookie_value');
  ctx.body = 'cookie setted';
});

app.listen(3001, (e) => {
    console.log('server listening port 3001');
});
複製代碼

進入'http://localhost:3001/'後去查看 cookie:

能夠看到服務端傳來的 cookie。

2. sessionStorage 和 localStorage

sessionStorage 和 localStorage 有與cookie不一樣的兩點:

  1. 存儲的數據被嚴格限制在本地
  2. 不會每次向服務器請求時都帶上存儲的數據

2.1 總述

sessionStorage 和 localStorage 都是 Storage 對象;都是以名值對的形式存儲數據,存儲數據的key和value都是字符串(string)類型,若是傳入的不是字符串類型,會被轉換爲字符串類型。

因此,若是想把非字符串類型的數據存進來,要預先手動進行編碼,取出來後要再進行解碼。

2.2 增刪改查數據的方法

這兩類對象有着相同的增刪改查數據的 api,因此能夠用其中的一個對象爲例子,來演示這些 api,這裏選擇 sessionStorage :

  1. setItem(key, value):將一個鍵值對的保存,若是兩次保存的key相同可是value不一樣,則後面的覆蓋前面的。
  2. getItem(key):獲取指定 key 對應的 value
  3. removeItem(key):刪除指定的 key 及其 value
  4. key(index):獲取指定位置的...
  5. clear():刪除全部數據

還有一個屬性:

  • length屬性:判斷存了多少名值對,上面key(index)方法中的參數 index 的範圍是 0 =< index <= length - 1

使用sessionStorage來演示上面的 api:

存入兩個鍵值對,使用 setItem(key, value)方法:

sessionStorage.setItem('key 1', 'value 1');
sessionStorage.setItem('key 2', 'value 2');
複製代碼

打開瀏覽器頁面的開發者工具,點擊Application選項卡,點擊左側的 session Storage,就能看到兩條剛剛保存的鍵值對了。

獲取兩個鍵對應的數據,使用 getItem(key)方法:

let value1 = sessionStorage.getItem('key 1');
let value2 = sessionStorage.getItem('key 2');

console.log(value1, value2); // value 1 value 2
複製代碼

刪除 'key 1'和其對應的數據,使用 removeItem(key)方法:

sessionStorage.removeItem('key 1');
複製代碼

從圖中能夠看到存儲的數據只剩下 key 2: value 2 了。

如今再添加幾條數據:

sessionStorage.setItem('key 3', 'value 3');
sessionStorage.setItem('key 4', 'value 4');
sessionStorage.setItem('key 5', 'value 5');
sessionStorage.setItem('key 6', 'value 6');
複製代碼

獲得:

輸出如今存儲的數據條數,也就是鍵值對的條數,並輸出最後一條,使用length屬性:

let key_value_count = sessionStorage.length;
console.log('如今存儲了 ' + key_value_count + ' 條數據'); // 如今存儲了 5 條數據
複製代碼

一次性刪除全部數據,使用 clear()方法:

sessionStorage.clear();
複製代碼

結果:

plus: 使用對象屬性語法設置與訪問數據

因爲 Storage 自己就是對象,因此也可使用通常對象的讀取與設置屬性的語法來存取對象,本質就是經過設置屬性和值的鍵值對來添加與讀取數據。

存取的方式也和普通對象同樣有兩種,分別是點號法和中括號語法,例以下面的例子:

sessionStorage.key1 = 'value 1';
console.log(sessionStorage.key1);

sessionStorage['key 2'] = 'value 2';
console.log(sessionStorage['key 2']);
複製代碼

結果如圖:

這種語法和 api 中的 setItemgetItem效果相同。

想刪除一個數據時,可使用 delete關鍵字,和刪除普通對象屬性的操做相同:

delete sessionStorage.key1;
delete sessionStorage['key 2'];
複製代碼

結果:

這和 removeItem的效果相同。

2.3 兩個 storage 的區別

sessionStorage 和 localStorage 的區別在聲明週期和做用域這兩點上,具體來講以下。

  1. 在聲明週期上
    • sessionStorage :
      1. 當瀏覽器的標籤頁被關閉時, 其中存的數據也會被刪除。
      2. 對於 Chrome 和 Firefox 來講,瀏覽器若是崩潰了,重啓以後的仍然會保存原來的數據。
      3. 對於一些有從新打開標籤頁功能的瀏覽器,用戶在關閉標籤頁後 sessionStorage 中的數據仍然存在。
    • localStorage : 當用戶手動清除瀏覽器的緩存時,它其中的數據纔會被清除。
  2. 在做用域上
    • sessionStorage :不一樣標籤頁沒法相互訪問 sessionStorage 中保存的數據,即便這兩個標籤頁訪問的是同一個頁面
    • localStorage :
      1. 訪問同協議、同域名、同端口的頁面共享一個 localStorage 。並且全部頁面都有修改的能力。
      2. 利用上面的特色,可使不一樣的標籤頁互相通訊,這要配合下面要說的 Storage 事件來講。

2.4 storage 事件

在 Storage 裏的數據被添加、修改、刪除時,會觸發 storage 事件,能夠在 window 對象上添加事件監聽程序 onstorage 來監聽事件,而且能夠獲取事件對象。

storage 事件對象上有以下幾個屬性:

  1. key: 設置或刪除的鍵名
  2. storageArea: localStorage 或 sessionStorage
  3. newValue: 修改後的值,若爲刪除操做則爲 null
  4. oldValue: 被更改以前的值
  5. url: 所在的地址

注意:localStorage 的事件採用的是廣播機制,正在訪問相同站點的頁面都會受到信息。這樣能夠完成必定的標籤頁之間的通訊。

參考:

MDN

《JavaScript高級程序設計》

《JavaScript權威指南》

相關文章
相關標籤/搜索