本文由雲+社區發表css
在前端面試中,有一個必問的問題:請你談談cookie和localStorage有什麼區別啊?html
localStorage是H5中的一種瀏覽器本地存儲方式,而實際上,cookie自己並非用來作服務器存儲的。但在 localStorage 出現以前,cookie被濫用當作了存儲工具,什麼數據都放在cookie中,即便這些數據只在頁面中使用、而不須要隨請求傳送到服務端(固然cookie也作了一些限制:大小受限、每一個域名下生成的cookie數量受限)。就像CSS中的float,最初被設計出來的初衷,是用於作文字環繞效果的,就是一個圖片、一段文字,給圖片加上float:left的樣式後,就會產生文字環繞圖片的效果。可是後來發現float結合<div>,能夠實現以前經過<table>實現的網頁佈局,所以就被「誤用於」網頁佈局了。前端
那麼經過閱讀本文,你能夠了解:web
1.cookie是什麼,cookie的屬性有哪些,如何設置cookie,cookie的缺點,和session的區別面試
2.再也不混淆cookie和webStorage,簡單介紹瀏覽器的本地存儲的兩種方式:sessionStorage和localStorageapi
cookie是當你瀏覽某個網站的時候,由web服務器存儲在你的機器硬盤上的一個小的文本文件。它其中記錄了你的用戶名、密碼、瀏覽的網頁、停留的時間等等信息。當你再次來到這個網站時,web服務器會先看看有沒有它上次留下來的cookie。若是有的話,會讀取cookie中的內容,來判斷使用者,並送出相應的網頁內容,好比在頁面顯示歡迎你的標語,或者讓你不用輸入ID、密碼就直接登陸等等。跨域
當客戶端要發送http請求時,瀏覽器會先檢查下是否有對應的cookie。有的話,則自動地添加在request header中的cookie字段。注意,每一次的http請求時,若是有cookie,瀏覽器都會自動帶上cookie發送給服務端。那麼把什麼數據放到cookie中就很重要了,由於不少數據並非每次請求都須要發給服務端,畢竟會增長網絡開銷,浪費帶寬。因此對於那設置「每次請求都要攜帶的信息(最典型的就是身份認證信息)」就特別適合放在cookie中,其餘類型的數據就不適合了。瀏覽器
簡單的說就是:緩存
(1) cookie是以小的文本文件形式(即純文本),徹底存在於客戶端;cookie保存了登陸的憑證,有了它,只須要在下次請求時帶着cookie發送,就沒必要再從新輸入用戶名、密碼等從新登陸了。安全
(2) 是設計用來在服務端和客戶端進行信息傳遞的;
這裏我簡單地畫了個圖,能夠方便理解:
第一次請求時:
第一次請求
下一次請求時:
下一次請求
瀏覽器會把cookie放到請求頭一塊兒提交給服務器,cookie攜帶了會話ID信息。服務器會根據cookie辨認用戶:因爲cookie帶了會話的ID信息,能夠經過cookie找到對應會話,經過判斷會話來判斷用戶狀態。
在瀏覽器的控制檯中,能夠直接輸入:document.cookie來查看cookie。cookie是一個由鍵值對構成的字符串,每一個鍵值對之間是「; 」即一個分號和一個空格隔開。
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選項用來設置「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是路徑,二者加起來就構成了 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也不會自動被添加到請求頭部中。
Cookie的大小
Secure選項用來設置cookie只在確保安全的請求中才會發送。當請求是HTTPS或者其餘安全協議時,包含 Secure選項的 cookie 才能被髮送至服務器。
默認狀況下,cookie不會帶Secure選項(即爲空)。因此默認狀況下,不論是HTTPS協議仍是HTTP協議的請求,cookie 都會被髮送至服務端。但要注意一點,Secure選項只是限定了在安全狀況下才能夠傳輸給服務端,但並不表明你不能看到這個 cookie。
補充:
若是想在客戶端即網頁中經過 js 去設置Secure類型的 cookie,必須保證網頁是https協議的。在http協議的網頁中是沒法設置secure類型cookie的。
這個選項用來設置cookie是否能經過 js 去訪問。默認狀況下,cookie不會帶httpOnly選項(即爲空),因此默認狀況下,客戶端是能夠經過js代碼去訪問(包括讀取、修改、刪除等)這個cookie的。當cookie帶httpOnly選項時,客戶端則沒法經過js代碼去訪問(包括讀取、修改、刪除等)這個cookie。
在客戶端是不能經過js代碼去設置一個httpOnly類型的cookie的,這種類型的cookie只能經過服務端來設置。
能夠在瀏覽器的控制檯中看出哪些cookie是httpOnly類型的,HTTP下帶綠色對勾的便是,如圖:
httponly
只要是httponly類型的,在控制檯經過document.cookie是獲取不到的,也不能進行修改。
之因此限制客戶端去訪問cookie,主要仍是出於安全的目的。由於若是任何 cookie 都能被客戶端經過document.cookie獲取,那麼假如合法用戶的網頁受到了XSS攻擊,有一段惡意的script腳本插到了網頁中,這個script腳本,經過document.cookie讀取了用戶身份驗證相關的 cookie,那麼只要原樣轉發cookie,就能夠達到目的了。
cookie既能夠由服務端來設置,也能夠由客戶端來設置。
前面1.1中介紹過,客戶端第一次向服務端請求時,在相應的請求頭中就有set-cookie字段,用來標識是哪一個用戶。
下圖我是登陸騰訊雲的某個頁面的響應頭截圖,能夠看到響應頭中有兩個set-cookie字段,每段對應一個cookie,注意每一個cookie放一個set-cookie字段中,不能將多個cookie放在一個set-cookie字段中。具體每一個cookie設置了相關的屬性:expires、path、httponly,具體屬性含義能夠結合1.2 cookie的屬性來看:
response headers
服務端設置cookie的範圍:
服務端能夠設置cookie 的全部選項:expires、domain、path、secure、HttpOnly
cookie不像web Storage有setItem,getItem,removeItem,clear等方法,須要本身封裝。簡單地在瀏覽器的控制檯裏輸入:
document.cookie="name=lynnshen; age=18"
但發現只添加了第一個cookie:"name=lynnshen",後面的cookie並無添加進來:
最簡單的設置多個cookie的方法就是重複執行document.cookie = "key=name":
document.cookie = "name=lynnshen"; document.cookie = "age=18";
再看控制檯:
注意:
當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表示:昨天就過時了,趕忙刪除 }
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的方法;
cookie是存在客戶端瀏覽器上,session會話存在服務器上。會話對象用來存儲特定用戶會話所需的屬性及配置信息。當用戶請求來自應用程序的web頁時,若是該用戶尚未會話,則服務器將自動建立一個會話對象。當會話過時或被放棄後,服務器將終止該會話。cookie和會話須要配合,具體內容參見1.1節。
當cookie失效、session過時時,就須要從新登陸了。
在較高版本的瀏覽器中,js提供了兩種存儲方式:sessionStorage和globalStorage。在H5中,用localStorage取代了globalStorage。
sessionStorage用於本地存儲一個會話中的數據,這些數據只有在同一個會話中的頁面才能訪問,而且當會話結束後,數據也隨之銷燬。因此sessionStorage僅僅是會話級別的存儲,而不是一種持久化的本地存儲。
localStorage是持久化的本地存儲,除非是經過js刪除,或者清除瀏覽器緩存,不然數據是永遠不會過時的。
瀏覽器的支持狀況:IE7及如下版本不支持web storage,其餘都支持。不過在IE五、IE六、IE7中有個userData,其實也是用於本地存儲。這個持久化數據放在緩存中,只有不清理緩存,就會一直存在。
(1) web storages和cookie的做用不一樣,web storage是用於本地大容量存儲數據(web storage的存儲量大到5MB);而cookie是用於客戶端和服務端間的信息傳遞;
(2) web storage有setItem、getItem、removeItem、clear等方法,cookie須要咱們本身來封裝setCookie、getCookie、removeCookie,具體可見1.3節;
本文縱向上深度介紹了cookie相關的知識,包括cookie的做用、各個屬性的用途、cookie的設置、缺點等等。橫向上,將cookie和會話、localStorage作了比較。若有問題,歡迎指正。
此文已由做者受權騰訊雲+社區發佈
搜索關注公衆號「雲加社區」,第一時間獲取技術乾貨,關注後回覆1024 送你一份技術課程大禮包!