2020前端面試-瀏覽器儲存機制篇

qq_41800649發表於2020-10-06

1.總述:

  • WebApp 優異的效能表現,有一部分原因要歸功於瀏覽器儲存技術的提升。
  • cookie儲存資料的功能已經很難滿足開發所需,逐漸被WebStorage、IndexedDB所取代

2.Cookie:

(1)來源:

  • HTTP是一種無狀態的協議,客戶端與伺服器建立連線並傳輸資料後,連線就會關閉。再次互動資料需要建立新的連線,因此,伺服器也無法知道使用者上一次做了什麼。

  • Cookie是用來繞開HTTP的無狀態性的手段之一,伺服器可以設定或讀取Cookies中包含的資訊,藉此維護使用者跟伺服器會話中的狀態。

  • 比如在使用者在購物網站上選擇了一個商品後,伺服器會發來一段cookie,裡面儲存了該商品的資訊,然後在另一個頁面選擇了其他商品後,瀏覽器會把Cookie傳送給伺服器,伺服器就知道他之前選購了什麼。

(2)實現原理:

  • 客戶端請求伺服器後,伺服器會在響應頭中通過set-cookie欄位傳送**包含登入憑據的Cookie**到客戶端
  • 瀏覽器在收到響應後會對該Cookie進行儲存(記憶體或硬碟)。
  • 使用者再次傳送請求時,會在請求頭中通過cookie欄位將該Cookie傳送到伺服器,然後伺服器會對這個cookie進行使用者身份,狀態等驗證。

生成cookie的兩種方式:

  1. 伺服器端在響應報文中新增set-cookie欄位,通過ket-value的形式傳送

    //伺服器端傳送Cookie
    Set-Cookie: sid=121231
    Set-Cookie: system:window_x64
    //客戶端傳送Cookie
    Cookie: sid=121231; system=window_x64
    
  2. 在js中通過document.cookie來讀寫cookie

    document.cookie="userName=hellol;domain=.baidu.com";
    

(3)Set-Cookie欄位中可以設定的屬性:

image-20201005160706815

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-3qCNabwr-1601978817745)(C:\Users\劉小康\AppData\Roaming\Typora\typora-user-images\image-20201005160734368.png)]

  • 有效期方面的屬性:時間一到,瀏覽器會自動刪除cookie檔案

    • Expires屬性:用的是絕對時間點
    • Max-Age屬性:用的是相對時間,單位是秒,瀏覽器用收到報文的時間點再加上 Max-Age,就可以得到失效的絕對時間。
    • 瀏覽器會優先採用 Max-Age 計算有效期。
  • 作用域方面的屬性:(為了安全,讓瀏覽器僅傳送cookie給特定的伺服器和 URI,避免被其他網站盜用。)

    • domain屬性:指定Cookie 所屬的域名,指定只有該域名下的網站才可以訪問該Cookie,例如要讓Cookie在a.test.com下可以訪問,但在b.test.com下不能訪問,則可將domain設定成a.test.com。

    • path屬性:指定Cookie 所屬的路徑。瀏覽器在傳送 Cookie 前會從 URI 中提取出 host 和 path 部分,如果與cookie中的path不同,就不會在請求頭裡傳送 Cookie。

  • 安全性方面的屬性:(為了不要讓伺服器以外的人看到)

    • HttpOnly屬性:Cookie 只能通過HTTP 協議傳輸,禁止通過其他方式訪問,例如會禁止通過js訪問cookie,這樣就減少了跨站指令碼(XSS)攻擊。

    • Secure屬性:只能在協議為HTTPS的請求中攜帶cookie。

(4)Cookie如何防範跨站指令碼(XSS)攻擊:

跨站指令碼功能是指攻擊者在返回的HTML中嵌入javascript指令碼,然後利用js盜取使用者的cookie資料。

為了減輕這些攻擊,需要在傳送http請求時,在請求頭中新增set-cookie欄位的HttpOnly屬性和Secure屬性

跨站指令碼(XSS)攻擊的其他防範方法:對輸入的url進行過濾,對輸出的頁面內容進行編碼,阻止js指令碼的執行。

跨站請求偽造(CSRF)是指攻擊者欺騙使用者點選連結,使其偽造了一個請求。可以通過新增token進行驗證。

(5)儲存型別:

Cookie是由客戶端儲存的,按其儲存位置可分為:記憶體式Cookie和硬碟式Cookie

記憶體式Cookie儲存在記憶體中,瀏覽器關閉後就會消失,由於其儲存時間較短,因此也被稱為非持久Cookie會話Cookie

硬碟式Cookie儲存在硬碟中,其不會隨瀏覽器的關閉而消失,除非手工清除或自動過期。由於硬碟式Cookie儲存時間是長期的,因此也被稱為持久Cookie

(6)應用場景:

  • 一般都是用來維護使用者的登入狀態,即登入的時候選擇記住密碼,永久cookie就會被寫在客戶端電腦,下次登入時,自動將cookie資訊附加傳送給服務端。
  • 購物車功能
  • 記錄使用者的瀏覽記錄,進行廣告推薦

(7)缺陷:

  • Cookie 不夠大,只能儲存4KB的資料。

  • 過多的Cookie會帶來巨大的效能消耗,因為Cookie 是緊跟域名的。同一個域名下的所有請求,都會攜帶 Cookie。

    • 對於靜態檔案的獲取,不必在請求中加上cookie,可以將靜態檔案放在CDN上,這樣請求的域名就與主站的域名分開了。
  • 安全性問題,在http請求中cookie是通過明文傳輸的,使用https協議可以解決這個安全性問題。

HTML5中新增了本地儲存的解決方案----Web Storage,它分成兩類:sessionStorage和localStorage。

3.localStorage:

特點:

  • 儲存的資料長期存在
  • 儲存大小為5M左右
  • 介面封裝較好

使用方法:

//存資料
localStorage.setItem('name','liu')
//取資料
var name=localStorage.getItem('name')

應用場景:傾向於用來儲存一些內容穩定的資源。比如圖片內容豐富的電商網站會用它來儲存 Base64 格式的圖片字串

4.sessionStorage:

特點:

  • 會話級別的瀏覽器儲存
  • 儲存大小也為5M左右
    • 介面封裝較好

使用方法:

//存資料
sessionStorage.setItem('name','liu')
//取資料
var name=sessionStorage.getItem('name')

應用場景:用來儲存會話級別的資訊,當前頁面的瀏覽記錄;

5.Cookie、localStorage、sessionStorage的區別:

  • 共同點:都是儲存在瀏覽器端,且都遵循同源策略。
  • 不同點:生命週期,作用域,儲存容量的不同
CookielocalStoragesessionStorage
生命週期在設定的失效時間到來之前一直有效。持久化的本地儲存,永久不會過期,只有手動刪除臨時性的本地儲存,會話級別的儲存,當會話結束(頁面被關閉)時,儲存內容也隨之被釋放
作用域只有指定的域名和路徑可以訪問所有同源視窗可以共享只存在於當前視窗
儲存容量4KB5M5M

說到底,Web Storage 是對 Cookie 的擴充,它只能用於儲存少量的簡單資料。當遇到大規模的、結構複雜的資料時,Web Storage 也愛莫能助了。這時候我們就要清楚我們的終極大 boss——IndexedDB!

6.IndexedDB:

特點:

  • 非關係型資料庫,可以儲存大量的結構化資料

  • 擁有豐富的查詢能力

  • 支援事務回滾

  • 支援儲存二進位制資料(ArrayBuffer物件和Blob物件)

三種會話跟蹤技術:cookie,session,token

7.Cookie和Session的區別:

注意:Session指的是伺服器端的快取,而sessionStorage屬於webStorage的一種,是瀏覽器端的快取。

相同點:兩者都是會話跟蹤的技術,都是用來儲存使用者的資訊

不同點:

  • 存放位置不同:cookie存放於客戶端,session存放於伺服器端
  • 安全性:cookie容易被竊取,不能存放敏感的資訊,比如銀行卡資訊。考慮到安全性問題的話,應當使用session。
  • 伺服器效能:session會在一定時間內儲存在伺服器上。當訪問增多時,會佔用伺服器的效能。考慮到減輕伺服器效能方面,可以使用cookie。
  • 儲存物件:cookie儲存的是字串,session儲存的是物件
  • 作用域:伺服器端的session是共享的,而cookie的作用域受到域名和路徑的影響。

8.Cookie和Session的聯合使用:

使用者身份驗證需要通過客戶端的cookie和伺服器端的session聯合實現:

1、使用者向伺服器傳送使用者名稱和密碼。

2、伺服器驗證通過後,在當前對話(session)裡面儲存相關資料,比如使用者角色、登入時間等等。

3、伺服器向使用者返回一個 session_id,寫入使用者的 Cookie。

4、使用者隨後的每一次請求,都會通過 Cookie,將 session_id 傳回伺服器。

5、伺服器收到 session_id,找到前期儲存的資料,由此得知使用者的身份。

9.Token與Session:

伺服器端使用session進行登入認證的問題:

  • 針對每一個使用者都需要儲存一個session,當越來越多的使用者發請求時,記憶體的開銷也會不斷增加。
  • 伺服器叢集需要同步所有的sesssion。

基於token的身份驗證過程:

  • 使用者傳送登入請求。

  • 服務端返回一個簽名的token 給客戶端

  • 客戶端儲存token,每次傳送請求的時候都帶上這個token

  • 伺服器端驗證token並返回資料。

  • 整個過程伺服器端需要做的就是生成token,驗證token,不需要再儲存使用者的身份資訊。

token的優點:

  • 安全性:由於token是經過簽名認證的,所以可以防範CSRF(跨站請求偽造)
  • 可擴充套件性:Token能夠建立與其它程式共享許可權的程式。

10.如何實現不同標籤頁之間的通訊

考察的是資料儲存的知識,資料儲存有本地和伺服器儲存兩種方式,這裡前端我們只考慮本地儲存

https://blog.csdn.net/qq_21729177/article/details/78028243

方法一:使用localStorage

原理:當同源頁面的某個頁面修改了localStorage,其餘的同源頁面只要註冊了storage事件,就會觸發

//tab1  通過localStorage新增快取
btn.onclick = function () {
    window.localStorage.setItem("name", "liu");
};

//tab2 使用storae事件監聽快取增刪改的動作
window.addEventListener("storage", function (event) {
    //event.key中儲存的是發生改變的cookie的鍵
    //event.newValue儲存的對應的值
    if(event.key=="name"){
		console.log(event.newValue)
    }
    alert("本地儲存的資料有改變哦" + event.key + event.newValue);
});

方法二:通過postMessage實現跨域通訊

應用場景:通過iframe有依賴關係的兩個頁面的通訊

原理:通過window.postMessage傳送訊息,通過onMessage來監聽訊息

tab1: 引入iframe的頁面

<body>
    <input type="text" id="input" />
    <button onclick="sendMessage()">點選向iframe傳送資料</button><br />
    <iframe
            src="http://127.0.0.1:5500/3.test2.html"
            frameborder="0"
            allow=""
            id="iframe"
            ></iframe>
</body>
<script>
    function sendMessage() {

        // 1.獲取iframe視窗的引用

        // 方法一:直接獲取iframe的contentWindow屬性
        // contentWindow 屬性返回當前HTMLIFrameElement的Window物件. 你可以使用這個Window 物件去訪問這個iframe的文件和它內部的DOM
        // var win = iframe.contentWindow;

        // 方法二:通過window.frames獲取
        // 返回的是frame物件的集合,一個類陣列物件,列出了當前視窗的所有直接子視窗
        var win = frames[0];

        // 2.向指定的視窗傳送資料
        //otherWindow.postMessage(message, targetOrigin);
        //2.1 otherwindow表示指定的視窗,可以有三種情況:
        //可以是iframe的contentWindow屬性
        //也可以是window.open返回的視窗物件
        //還可以是window.frames中的子視窗        
        //2.2 第一個引數message表示要傳送的訊息
        //2.3 第二個參數列示目標視窗的地址。注意:如果是/,則表示只傳送訊息給同源的頁面;如果是*就表示將資料傳送給全部頁面。
        win.postMessage(input.value, "http://127.0.0.1:5500");
    }
</script>

tab2: iframe原頁面

<body>
    <div
         id="iframe"
         style="width: 500px; height: 500px; background-color: skyblue"
         >
        這是內嵌的iframe
    </div>
</body>
<script>
    //   監聽通過postMessage向自己發來的資料
    window.addEventListener("message", function (e) {
        console.log(e);
        // e.target表示傳送方的原地址
        // e.data表示傳送過來的資料
        // e.source表示對傳送訊息的視窗物件(即window物件)的引用,可以利用繼續使用這個屬性向原地址返回資料			 
        // e.source.postMessage()
        iframe.innerHTML = e.data;
    });
</script>

參考連結

相關文章