一文帶你看懂cookie,面試前端不用愁

騰訊雲加社群發表於2018-12-11

本文由雲+社群發表

在前端面試中,有一個必問的問題:請你談談cookie和localStorage有什麼區別啊?

localStorage是H5中的一種瀏覽器本地儲存方式,而實際上,cookie本身並不是用來做伺服器儲存的。但在 localStorage 出現之前,cookie被濫用當做了儲存工具,什麼資料都放在cookie中,即使這些資料只在頁面中使用、而不需要隨請求傳送到服務端(當然cookie也做了一些限制:大小受限、每個域名下生成的cookie數量受限)。就像CSS中的float,最初被設計出來的初衷,是用於做文字環繞效果的,就是一個圖片、一段文字,給圖片加上float:left的樣式後,就會產生文字環繞圖片的效果。但是後來發現float結合

,可以實現之前通過實現的網頁佈局,因此就被“誤用於”網頁佈局了。

那麼通過閱讀本文,你可以瞭解:

1.cookie是什麼,cookie的屬性有哪些,如何設定cookie,cookie的缺點,和session的區別

2.不再混淆cookie和webStorage,簡單介紹瀏覽器的本地儲存的兩種方式:sessionStorage和localStorage

1.cookie

1.1 cookie是什麼

cookie是當你瀏覽某個網站的時候,由web伺服器儲存在你的機器硬碟上的一個小的文字檔案。它其中記錄了你的使用者名稱、密碼、瀏覽的網頁、停留的時間等等資訊。當你再次來到這個網站時,web伺服器會先看看有沒有它上次留下來的cookie。如果有的話,會讀取cookie中的內容,來判斷使用者,並送出相應的網頁內容,比如在頁面顯示歡迎你的標語,或者讓你不用輸入ID、密碼就直接登入等等。

當客戶端要傳送http請求時,瀏覽器會先檢查下是否有對應的cookie。有的話,則自動地新增在request header中的cookie欄位。注意,每一次的http請求時,如果有cookie,瀏覽器都會自動帶上cookie傳送給服務端。那麼把什麼資料放到cookie中就很重要了,因為很多資料並不是每次請求都需要發給服務端,畢竟會增加網路開銷,浪費頻寬。所以對於那設定“每次請求都要攜帶的資訊(最典型的就是身份認證資訊)”就特別適合放在cookie中,其他型別的資料就不適合了。

簡單的說就是:

(1) cookie是以小的文字檔案形式(即純文字),完全存在於客戶端;cookie儲存了登入的憑證,有了它,只需要在下次請求時帶著cookie傳送,就不必再重新輸入使用者名稱、密碼等重新登入了。

(2) 是設計用來在服務端客戶端進行資訊傳遞的;

這裡我簡單地畫了個圖,可以方便理解:

第一次請求時:

img
第一次請求

下一次請求時:

img
下一次請求

瀏覽器會把cookie放到請求頭一起提交給伺服器,cookie攜帶了會話ID資訊。伺服器會根據cookie辨認使用者:由於cookie帶了會話的ID資訊,可以通過cookie找到對應會話,通過判斷會話來判斷使用者狀態。

1.2 cookie的屬性

在瀏覽器的控制檯中,可以直接輸入:document.cookie來檢視cookie。cookie是一個由鍵值對構成的字串,每個鍵值對之間是“; ”即一個分號和一個空格隔開。

img
document.cookie

注意,這個方法只能獲取非 HttpOnly 型別的cookie

每個cookie都有一定的屬性,如什麼時候失效,要傳送到哪個域名,哪個路徑等等。這些屬性是通過cookie選項來設定的,cookie選項包括:expires、domain、path、secure、HttpOnly。在設定任一個cookie時都可以設定相關的這些屬性,當然也可以不設定,這時會使用這些屬性的預設值。在設定這些屬性時,屬性之間由一個分號和一個空格隔開。程式碼示例如下:

"key=name; expires=Sat, 08 Sep 2018 02:26:00 GMT; domain=ppsc.sankuai.com; path=/; secure; HttpOnly"
複製程式碼

cookie的屬性可以在控制檯檢視:Application選項,左邊選擇Storage,最後一個就是cookie,點開即可檢視。

  • Expires、Max Age:

Expires選項用來設定“cookie 什麼時間內有效”。Expires其實是cookie失效日期,Expires必須是 GMT 格式的時間(可以通過 new Date().toGMTString()或者 new Date().toUTCString() 來獲得)。

new Date().toGMTString()或者 new Date().toUTCString()
複製程式碼

如expires=Sat, 08 Sep 2018 02:26:00 GMT表示cookie將在2018年9月8日2:26分之後失效。對於失效的cookie瀏覽器會清空。如果沒有設定該選項,這樣的cookie稱為會話cookie。它存在記憶體中,當會話結束,也就是瀏覽器關閉時,cookie消失。

補充:

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和Path

Domain是域名,Path是路徑,兩者加起來就構成了 URL,Domain和Path一起來限制 cookie 能被哪些 URL 訪問。即請求的URL是Domain或其子域、且URL的路徑是Path或子路徑,則都可以訪問該cookie,例如:

某cookie的 Domain為“baidu.com”, Path為“/ ”,若請求的URL(URL 可以是js/html/img/css資源請求,但不包括 XHR 請求)的域名是“baidu.com”或其子域如“api.baidu.com”、“dev.api.baidu.com”,且 URL 的路徑是“/ ”或子路徑“/home”、“/home/login”,則都可以訪問該cookie。

補充:

發生跨域xhr請求時,即使請求URL的域名和路徑都滿足 cookie 的 Domain和Path,預設情況下cookie也不會自動被新增到請求頭部中。

  • Size

Cookie的大小

  • Secure

Secure選項用來設定cookie只在確保安全的請求中才會傳送。當請求是HTTPS或者其他安全協議時,包含 Secure選項的 cookie 才能被髮送至伺服器。

預設情況下,cookie不會帶Secure選項(即為空)。所以預設情況下,不管是HTTPS協議還是HTTP協議的請求,cookie 都會被髮送至服務端。但要注意一點,Secure選項只是限定了在安全情況下才可以傳輸給服務端,但並不代表你不能看到這個 cookie。

補充:

如果想在客戶端即網頁中通過 js 去設定Secure型別的 cookie,必須保證網頁是https協議的。在http協議的網頁中是無法設定secure型別cookie的。

  • httpOnly

這個選項用來設定cookie是否能通過 js 去訪問。預設情況下,cookie不會帶httpOnly選項(即為空),所以預設情況下,客戶端是可以通過js程式碼去訪問(包括讀取、修改、刪除等)這個cookie的。當cookie帶httpOnly選項時,客戶端則無法通過js程式碼去訪問(包括讀取、修改、刪除等)這個cookie。

在客戶端是不能通過js程式碼去設定一個httpOnly型別的cookie的,這種型別的cookie只能通過服務端來設定。

可以在瀏覽器的控制檯中看出哪些cookie是httpOnly型別的,HTTP下帶綠色對勾的即是,如圖:

img
httponly

只要是httponly型別的,在控制檯通過document.cookie是獲取不到的,也不能進行修改。

之所以限制客戶端去訪問cookie,主要還是出於安全的目的。因為如果任何 cookie 都能被客戶端通過document.cookie獲取,那麼假如合法使用者的網頁受到了XSS攻擊,有一段惡意的script指令碼插到了網頁中,這個script指令碼,通過document.cookie讀取了使用者身份驗證相關的 cookie,那麼只要原樣轉發cookie,就可以達到目的了。

1.3 cookie的設定、讀取、刪除方法

cookie既可以由服務端來設定,也可以由客戶端來設定。

1.3.1 服務端設定cookie

前面1.1中介紹過,客戶端第一次向服務端請求時,在相應的請求頭中就有set-cookie欄位,用來標識是哪個使用者。

下圖我是登入騰訊雲的某個頁面的響應頭截圖,可以看到響應頭中有兩個set-cookie欄位,每段對應一個cookie,注意每個cookie放一個set-cookie欄位中,不能將多個cookie放在一個set-cookie欄位中。具體每個cookie設定了相關的屬性:expires、path、httponly,具體屬性含義可以結合1.2 cookie的屬性來看:

img
response headers

服務端設定cookie的範圍:

服務端可以設定cookie 的所有選項:expires、domain、path、secure、HttpOnly

1.3.2 客戶端設定cookie

cookie不像web Storage有setItem,getItem,removeItem,clear等方法,需要自己封裝。簡單地在瀏覽器的控制檯裡輸入:

document.cookie="name=lynnshen; age=18"
複製程式碼

但發現只新增了第一個cookie:"name=lynnshen",後面的cookie並沒有新增進來:

img

最簡單的設定多個cookie的方法就是重複執行document.cookie = "key=name":

document.cookie = "name=lynnshen";
document.cookie = "age=18";
複製程式碼

再看控制檯:

img

注意:

當name、domain、path 這3個欄位都相同的時候,cookie會被覆蓋。

下面是我自己簡單封裝的設定、讀取、刪除cookie的方法:

設定cookie:

function setCookie(name,value,iDay){
    var oDate = new Date();
    oDate.setDate(oDate.getDate() + iDay);
    document.cookie = name + "=" + value + ";expires=" + oDate;
}
複製程式碼

讀取cookie,該方法簡單地認為cookie中只有一個“=”,即key=value,如有更多需求可以在此基礎上完善:

function getCookie(name){
    //例如cookie是"username=abc; password=123"
    var arr = document.cookie.split('; ');//用“;”和空格來劃分cookie
    for(var i = 0 ;i < arr.length ; i++){
        var arr2 = arr[i].split("=");
        if(arr2[0] == name){
            return arr2[1];
        }
    }
    return "";//整個遍歷完沒找到,就返回空值
}
複製程式碼

刪除cookie:

function removeCookie(name){
    setCookie(name, "1", -1)//第二個value值隨便設個值,第三個值設為-1表示:昨天就過期了,趕緊刪除
}
複製程式碼

1.4 cookie的缺點

cookie的缺點:

(1) 每個特定域名下的cookie數量有限:

IE6或IE6-(IE6以下版本):最多20個cookie

IE7或IE7+(IE7以上版本):最多50個cookie

FF:最多50個cookie

Opera:最多30個cookie

Chrome和safari沒有硬性限制

當超過單個域名限制之後,再設定cookie,瀏覽器就會清除以前設定的cookie。IE和Opera會清理近期最少使用的cookie,FF會隨機清理cookie;

(2) 儲存量太小,只有4KB;

(3) 每次HTTP請求都會傳送到服務端,影響獲取資源的效率;

(4) 需要自己封裝獲取、設定、刪除cookie的方法;

1.5 cookie和session的區別

cookie是存在客戶端瀏覽器上,session會話存在伺服器上。會話物件用來儲存特定使用者會話所需的屬性及配置資訊。當使用者請求來自應用程式的web頁時,如果該使用者還沒有會話,則伺服器將自動建立一個會話物件。當會話過期或被放棄後,伺服器將終止該會話。cookie和會話需要配合,具體內容參見1.1節。

當cookie失效、session過期時,就需要重新登入了。

2.瀏覽器本地儲存:

2.1 localStorage和sessionStorage

在較高版本的瀏覽器中,js提供了兩種儲存方式:sessionStorage和globalStorage。在H5中,用localStorage取代了globalStorage。

sessionStorage用於本地儲存一個會話中的資料,這些資料只有在同一個會話中的頁面才能訪問,並且當會話結束後,資料也隨之銷燬。所以sessionStorage僅僅是會話級別的儲存,而不是一種持久化的本地儲存。

localStorage是持久化的本地儲存,除非是通過js刪除,或者清除瀏覽器快取,否則資料是永遠不會過期的。

瀏覽器的支援情況:IE7及以下版本不支援web storage,其他都支援。不過在IE5、IE6、IE7中有個userData,其實也是用於本地儲存。這個持久化資料放在快取中,只有不清理快取,就會一直存在。

2.2 web storage和cookie的區別

(1) web storages和cookie的作用不同,web storage是用於本地大容量儲存資料(web storage的儲存量大到5MB);而cookie是用於客戶端和服務端間的資訊傳遞;

(2) web storage有setItem、getItem、removeItem、clear等方法,cookie需要我們自己來封裝setCookie、getCookie、removeCookie,具體可見1.3節;

3.小結

本文縱向上深度介紹了cookie相關的知識,包括cookie的作用、各個屬性的用途、cookie的設定、缺點等等。橫向上,將cookie和會話、localStorage做了比較。如有問題,歡迎指正。

此文已由作者授權騰訊雲+社群釋出

搜尋關注公眾號「雲加社群」,第一時間獲取技術乾貨,關注後回覆1024 送你一份技術課程大禮包!

相關文章