1. 緩存分類
- 服務器端緩存(CDN緩存)贮缅;
- 客戶端緩存(瀏覽器緩存);
2. 瀏覽器緩存
2.1. 強緩存
??????瀏覽器在加載某個資源時介却,先根據(jù)這個資源的一些http header判斷它是否命中強緩存谴供,如果命中,瀏覽器直接從自己的緩存中讀取資源齿坷,不會發(fā)送請求到服務器桂肌。比如瀏覽器在加載某個css文件所在的網(wǎng)頁時数焊,發(fā)現(xiàn)這個css文件的緩存配置命中了強緩存,瀏覽器就直接從緩存中加載這個css文件轴或,連請求都不會發(fā)送到網(wǎng)頁所在的服務器昌跌。
2.2. 協(xié)商緩存
??????當強緩存沒有命中的時候,瀏覽器一定會發(fā)送一個請求到服務器照雁,服務器依據(jù)資源的另外一些HTTP header驗證這個資源是否命中協(xié)商緩存蚕愤。
??????1)命中協(xié)商緩存:服務器返回(304),且不會攜帶請求資源的數(shù)據(jù)饺蚊,而是告訴瀏覽器可以直接從自己的緩存中加載所請求資源萍诱,于是瀏覽器又從自己的緩存中去加載資源;
??????2)未命中協(xié)商緩存:服務器將資源返回客戶端(200)污呼,并更新本地緩存數(shù)據(jù)裕坊。
2.3. 協(xié)商緩存與強緩存的區(qū)別
??????強緩存不發(fā)送請求到服務器,協(xié)商緩存會發(fā)送請求到服務器燕酷。
2.4. 緩存設置方法
2.4.1 HTML Meta標簽控制緩存(非HTTP協(xié)議定義)
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
??????上述代碼的作用是告訴瀏覽器當前頁面不被緩存籍凝,每次訪問都需要去服務器拉取數(shù)據(jù),這種方法使用上很簡單苗缩,但只有部分瀏覽器可以支持饵蒂,而且有緩存代理的服務器都不支持,因為代理不解析HTML內容本身酱讶。
2.4.2. HTTP頭信息控制緩存
??????HTTP頭信息控制緩存是通過Expires(強緩存)退盯、Cache-control(強緩存)、Last-Modified/If-Modified-Since(協(xié)商緩存)泻肯、Etag/If-None-Match(協(xié)商緩存)實現(xiàn).
2.4.2.1. Expires
??????是Http1.0提出的一個表示資源過期時間的header渊迁,它描述的是一個絕對時間,由服務器返回灶挟,用GMT格式的字符串表示琉朽,如:
Expires:Thu,31 Dec 2016 23:55:55 GMT
??????讀取緩存數(shù)據(jù)條件:緩存過期時間(服務器返回的)<當前時間(客戶端當前時間);
??????缺點:Expires是較老的強緩存管理header稚铣,由于它是服務器返回的一個絕對時間箱叁,因此如果客戶端的時間與服務器的時間相差很大(比如時鐘不同步,或者跨時區(qū))榛泛,那么誤差就較大,所以在HTTP1.1版本開始噩斟,使用 Cache-Control: max-age=x 代替曹锨;
2.4.2.2. Cache-Control
??????Cache-Control:描述的是一個相對時間,在進行緩存命中的時候剃允,都是利用客戶端時間進行判斷沛简,所以相比較Expires齐鲤,Cache-Control的緩存管理更加有效,安全一些椒楣。
??????讀取緩存的數(shù)據(jù)條件:上次緩存時間(客戶端的)+max-age<當前時間(客戶端的)给郊;
??????Cache-Control值:
??????1)public:指示響應可被任何緩存區(qū)緩存;
??????2)private:指示對于單個用戶的整個或部分響應消息捧灰,不能被共享緩存處理淆九,這允許服務器僅僅描述當前用戶的部分響應消息,此響應消息對于其他用戶的請求無效毛俏;
??????3)no-cache:請求或響應消息不能緩存炭庙,該選項并不是說可以設置“不緩存”,而是需要和服務器確認煌寇;
??????4)no-store:在請求消息中發(fā)送將使得請求和響應消息都不使用緩存焕蹄,完全存不下來;
??????5)max-age:指示客戶機可以接收生存期不大于指定時間阀溶,以秒為單位的響應腻脏;
??????注意:在response header中,Expires和Cache-Control同時存在時银锻,Cache-Control的優(yōu)先級高于Expires永品,這兩個header可以只啟用一個,也可以同時啟用徒仓。
2.4.2.3. Last-Modified/If-Modified-Since
??????Last-Modified:需要配合 Cache-Control 使用腐碱,Last-Modified 標志某個響應資源的最后修改時間;
??????If-Modified-Since:當資源過期時(例如Expires強緩存失效)掉弛,發(fā)現(xiàn)資源具有 Last-Modified 聲明症见,則再次向web服務器發(fā)送請求時帶上 If-Modified-Since,表示請求時間殃饿,web服務器收到請求后發(fā)現(xiàn)有頭 If-Modified-Since谋作,則與被請求資源的最后修改時間進行比對,若最后修改時間較新乎芳,說明資源被改動過遵蚜,則響應整個資源內容(寫在響應消息包體內),并返回200奈惑;若最后修改時間較舊吭净,說明資源無新修改,則響應HTTP 304(無需包體肴甸,節(jié)省流量)寂殉,告知瀏覽器繼續(xù)使用所保存的緩存;
??????缺點:Last-Modified標注的最后修改時間只能精確到秒級原在,如果某些文件在1秒鐘以內被修改多次的話友扰,它將不能準確標注文件的修改時間(無法及時更新文件)彤叉;如果某些文件會被定期生成,當有時內容并沒有任何變化村怪,但Last-Modified卻被改變了秽浇,導致文件沒法使用緩存,有可能存在服務器沒有準確獲取文件修改時間甚负,或者與代理服務器時間不一致等情形(無法使用緩存)柬焕;
2.4.2.4. Etag/If-None-Match
??????也需要配合Cache-Control使用。
??????Etag:web服務器響應請求時腊敲,告訴瀏覽器當前資源在服務器的唯一標識(生成規(guī)則由服務器決定)击喂;
??????If-None-Match:當資源過期時(使用Cache-Control標識的max-age),發(fā)現(xiàn)資源具有Etag聲明碰辅,則再次向web服務器請求時帶上頭 If-None-Match(Etag的值)懂昂,web服務器收到請求后發(fā)現(xiàn)有頭 If-None-Match 則與被請求資源的相應校驗串進行比對,然后決定返回200或304没宾,Etag是服務器自動生成或由開發(fā)者生成的對應資源在服務器端的唯一標識符凌彬,能夠更加準確的控制緩存,Last-Modified 與 Etag 一起使用時循衰,服務器會優(yōu)先驗證Etag铲敛。
2.4.2.5. 瀏覽器緩存過程
??????狀態(tài)碼304:如果客戶端發(fā)送了一個帶條件的 GET 請求且該請求已被允許,而文檔的內容(自上次訪問以來或者根據(jù)請求的條件)并沒有改變会钝,則服務器應當返回304狀態(tài)碼伐蒋,簡單的表達就是:客戶端已經執(zhí)行了GET,但文件未變化迁酸。
3. 服務器端緩存
3.1. CDN緩存
??????CDN(Content Delivery Network內容分發(fā)網(wǎng)絡):屬于Cache服務器的一種先鱼,其目的是通過現(xiàn)在的Internet中增加一層新的網(wǎng)絡架構,將網(wǎng)站的內容發(fā)布到最接近用戶的網(wǎng)絡“邊緣”奸鬓,即通過調試系統(tǒng)將用戶的請求路由引導到離用戶接入網(wǎng)絡最近或者訪問效果最佳的緩存服務器上焙畔,由該緩存服務器為用戶提供內容服務。相對于直接訪問源站串远,這種方式縮短了用戶和內容之間的網(wǎng)絡距離宏多,從而達到加速的效果;使用戶可以就近取得所需的內容澡罚,解決Internet網(wǎng)絡擁塞狀況伸但,提高用戶訪問網(wǎng)站的響應速度,從技術上全面解決由于網(wǎng)絡帶寬小留搔、用戶訪問量大更胖、網(wǎng)點分布不均等原因,解決用戶訪問網(wǎng)站的響應速度慢的根本原因。
??????訪問過程:
??????1)用戶向瀏覽器提供要訪問的域名函喉;
??????2)瀏覽器調用域名解析庫對域名進行解析,由于CDN對域名解析過程進行了調整荣月,所以解析函數(shù)庫一般得到的是該域名對應的CNAME記錄管呵,為了得到實際IP地址,瀏覽器需要再次對獲得的CNAME域名進行解析以得到實際IP地址哺窄;在此過程中捐下,使用的全局負載均衡DNS解析,如根據(jù)地理位置信息解析對應的IP地址萌业,使用戶能就近訪問坷襟,此次解析得到的是CDN緩存服務器的IP地址;
??????3)瀏覽器得到實際IP地址生年,向緩存服務器發(fā)出訪問請求婴程;
??????4)若請求文件并未修改,返回304(充當服務器的角色)抱婉,若當前文件已經過期档叔,則緩存服務器根據(jù)提供的要訪問的域名,通過Cache內部專用DNS解析得到此域名的實際IP地址蒸绩,再由緩存服務器向此實際IP地址提交訪問請求衙四;
??????5)緩存服務器從實際IP地址得到內容以后,一方面在本地進行保存患亿,以備以后使用传蹈,另一方面把獲取的數(shù)據(jù)返回給客戶端,完成數(shù)據(jù)服務過程步藕;
??????6)客戶端得到由緩存服務器返回的數(shù)據(jù)以后顯示出來并完成整個數(shù)據(jù)請求過程惦界;
4. cookie與session
4.1. cookie
??????cookie:本地緩存機制,正統(tǒng)的cookie分發(fā)是通過擴展HTTP協(xié)議來實現(xiàn)的漱抓,服務器通過在 HTTP的響應頭中添加一行特殊的指示以提示瀏覽器按照指示生成相應的cookie表锻;用戶每請求一次服務器數(shù)據(jù),cookie則會隨著這些請求發(fā)送到服務器乞娄,服務器腳本語言如PHP等能夠處理cookie發(fā)送的數(shù)據(jù)瞬逊,可以說是非常方便的,當然前端也是可以生成cookie的仪或,用js對cookie的操作相當繁瑣确镊,瀏覽器只提供 document.cookie
這樣一個對象,對cookie的賦值范删,獲取都比較麻煩蕾域,而在PHP中可以通過setcookie()
來設置cookie,通過$_COOKIE
這個超全局數(shù)組來獲取cookie;
??????cookie的內容:主要包括:名字旨巷,值巨缘,過期時間,路徑和域采呐,路徑與域一起構成cookie的作用范圍若锁,路徑和域就是對應的域名,a網(wǎng)站的cookie自然不能給b用斧吐;若不設置過期時間又固,則表示這個cookie的生命期為瀏覽器會話期間,關閉瀏覽器窗口煤率,cookie就消失仰冠,這種生命期為瀏覽器會話期的cookie被稱為會話cookie,會話cookie一般不存儲在硬盤上而是保存在內存里蝶糯,當然這種行為并不是規(guī)范規(guī)定的洋只,若設置了過期時間,瀏覽器就會把cookie保存在硬盤上昼捍,關閉后再次打開瀏覽器木张,這些cookie仍然有效直到超過設定的過期時間,存儲在硬盤上的cookie可以在不同的瀏覽器進程間共享,比如兩個IE窗口,而對于保存在內存里的cookie州袒,不同的瀏覽器有不同的處理方式莺禁。
4.2. session
??????session:是一種服務器端的機制,服務器使用一種類似于散列表的結構來保存信息,當程序需要為某個客戶端的請求創(chuàng)建一個session標識(稱為session_id),如果已經包含則說明此前為此客戶端創(chuàng)建過session,服務器就按照session_id把這個session檢索出來使用,檢索不到會新建一個育拨;如果客戶端請求不包含session_id,則為此客戶端創(chuàng)建一個session并且生成一個與此session相關聯(lián)的session_id欢摄,session_id的值應該是一個既不會重復熬丧,又不容易被找到規(guī)律以仿造的字符串,這個session_id將在本次響應中返回給客戶端保存怀挠,同一客戶端啟動二次session_start的話析蝴,session_id是不一樣的,保存這個session_id的方式可以采用cookie绿淋,這樣在交互過程中瀏覽器可以自動的按照規(guī)則把這個標識發(fā)送給服務器闷畸,一般這個cookie的名字都是類似于session_id,但cookie可以被人為的禁止吞滞,則必須有其他機制以便在cookie被禁止時仍然能夠把session_id傳遞回服務器佑菩,經常使用的一種技術叫做URL重寫盾沫,就是把session_id直接附加在URL路徑的后面,比如:http://damonare.cn?sessionid=123456殿漠,還有一種技術叫做表單隱藏字段赴精,就是服務器會自動修改表單,添加一個隱藏字段绞幌,以便在表單提交時能夠把session_id傳遞回服務器祖娘。
??????session為什么出現(xiàn):HTTP本身是無狀態(tài)協(xié)議,即服務器無法識別兩個先后發(fā)送到服務器端的請求是否由同一個客戶端發(fā)起啊奄,因此對于每一個請求都要進行身份認證,而session是用來簡化這個認證過程的掀潮。
4.3. cookie和session的區(qū)別
??????1)cookie數(shù)據(jù)存放在客戶的瀏覽器上菇夸,session數(shù)據(jù)存放在服務器上;
??????2)cookie不是很安全仪吧,別人可以分析存放在本地的cookie并進行欺騙庄新,考慮到安全應當使用session,cookie是以明文形式存放在客戶端的薯鼠,安全性低择诈,可以通過一個加密算法來進行加密后存放,session存放于服務器的內存中出皇,所以安全性好羞芍;
??????3)session會在一定時間內保存在服務器上,當訪問增多郊艘,會比較占用服務器性能荷科,考慮到減輕服務器性能方面,應當使用cookie纱注;
??????4)單個cookie保存的數(shù)據(jù)不能超過4k畏浆,很多瀏覽器都限制在一個站點最多保存20個cookie,所以建議:將登錄信息等重要信息存放為session狞贱,其他信息如果需要保留刻获,可以放在cookie中;
??????5)cookie的生命周期是累計的瞎嬉,從創(chuàng)建時就開始計時蝎毡,20分鐘后,cookie生命周期結束氧枣;session的生命周期是間隔的顶掉,從創(chuàng)建時,開始計時如在20分鐘挑胸,沒有訪問session痒筒,那么session生命周期被銷毀,但是如果在20分鐘內(如在第19分鐘時)訪問過session,那么將重新計算session的生命周期簿透,關機會造成session生命周期的結束移袍,但是對cookie沒有影響;
??????6)訪問范圍:cookie為多個用戶瀏覽器共享老充,session為一個用戶瀏覽器獨享葡盗;
4.4. 為什么說session比cookie更安全
??????真正的cookie存在于客戶端硬盤上的一個文本文件,如果cookie和session一樣的話啡浊,只要cookie就好了觅够,讓客戶端來分擔服務器的負擔,并且對于用戶來說又是透明的巷嚣,但實際上并不是喘先;session的sessionID是放在cookie里的,要想攻破session的話廷粒,得分為兩步:
??????1)首先要得到session_id窘拯,攻破cookie后,得到session_id坝茎,session_id是要有人登錄涤姊,或者啟動session_start才會有,無法確定什么時候會有人登錄嗤放;
??????2)第二步是取有效的session_id思喊,session_id是加密的,第二次session_start的時候次酌,前一次的session_id就沒有用了搔涝,session過期時session_id也會失效,想在短時間內攻破加密的session_id很難和措,session是針對某一次的通信而言庄呈,會話結束session也就隨著消失了;
??????使session失效的方法:
??????1)關閉tomcat派阱;
??????2)重啟web應用诬留;
??????3)session時間到;
??????4)無效的session贫母;
5. token
5.1. token為什么出現(xiàn)
??????首先session的存儲是需要空間的文兑,其次,session的傳遞一般都是通過cookie來傳遞的腺劣,或者URL重寫的方式绿贞,而token在服務器是可以不需要存儲用戶的信息的,而token的傳遞方式也不限于cookie傳遞橘原,當然token也是可以保存起來的籍铁;
5.2. token的生成方式
??????瀏覽器第一次訪問服務器涡上,根據(jù)傳過來的唯一標識userID,服務端會通過一些算法拒名,如常用的HMAC-SHA256算法吩愧,然后加一個密鑰,生成一個token增显,然后通過BASE64編碼一下之后將這個token發(fā)送給客戶端雁佳,客戶端將token保存起來,下次請求時同云,帶著token糖权,服務器收到請求時,然后會用相同的算法和密鑰去驗證token炸站,如果通過星澳,執(zhí)行業(yè)務操作,不通過則返回不通過信息武契。
5.3. token(令牌)和session(會話)的區(qū)別
??????1)token和session存在都是為了身份驗證,服務器會保存一份session荡含,可能保存到緩存咒唆,文件或數(shù)據(jù)庫中;session和token都需要去管理過期時間释液;token和session的問題是一種時間與空間的博弈全释,session是空間換時間,而token是時間換空間误债,兩者的選擇要看具體情況而定浸船;
??????2)token和session都是“客戶端記錄,每次訪問攜帶”寝蹈,但token很容易設計為自包含的李命,即后端不需要記錄,每次發(fā)送一個無狀態(tài)請求箫老,每次解密驗證封字,每次當場得出合法/非法結論,這一切判斷依據(jù)耍鬓,除了固化在CS兩端的一些邏輯之外阔籽,整個信息是自包含的,是真正的無狀態(tài)牲蜀;而session_id一般都是一段隨機字符串笆制,需要到后端去檢索session_id的有效性,而服務器重啟可能會導致內存里的session沒了涣达;
??????3)案例比較:
??????session:我發(fā)給你一張身份證在辆,但只是一張寫著身體證號碼的紙片证薇,你每次來辦事,我去后臺查一下你的id是不是有效开缎;
??????token:我發(fā)給你一張加密的身份證棕叫,以后你只要出示這張卡片,我就知道你一定是自己人奕删;
??????4)安全性:作為身份認證token安全性比session好俺泣,因為每個請求都有簽名還能防止監(jiān)聽以及重放攻擊,而session就必須靠鏈路層來保障通訊安全完残,如果需要實現(xiàn)有狀態(tài)的會話,仍然可以增加session來在服務器端保存一些狀態(tài)谨设;
??????5)App通常用restful API跟服務器打交道熟掂,rest是無狀態(tài)的,即App不需要像瀏覽器那樣用cookie來保存session扎拣,因此用session或者token來標識自己就夠了赴肚,session由API服務器的邏輯處理,如果后端不是無狀態(tài)的rest API二蓝,那么可能需要在App里保存session誉券,可以在App里嵌入webkit,用一個隱藏的瀏覽器來管理cookie和session;
??????6)session是一種HTTP存儲機制刊愚,目的是為無狀態(tài)的HTTP提供持久機制踊跟,所謂session認證只是簡單的把user信息存儲到session里,因為session_id的不可預測性鸥诽,暫且認為是安全的商玫,這是一種認證手段;而token如果指的是OAuth Token或類似機制的話牡借,提供的是認證和授權拳昌,認證是針對用戶,授權是針對App钠龙,其目的是讓某App有權訪問某用戶的信息地回,這里的token是唯一的,不可以轉移到其它App上俊鱼,也不可以轉到其他用戶上刻像;而session只提供一種簡單的認證,即有此session_id并闲,即認為有此user的全部權利细睡,是需要嚴格保密的,這個數(shù)據(jù)應該只保存在站方帝火,不應該共享給其它網(wǎng)站或第三方App溜徙。簡單來說湃缎,如果用戶數(shù)據(jù)可能需要和第三方共享,或都允許第三方調用API接口蠢壹,用token嗓违;如果永遠只是自己的網(wǎng)站或App,用什么都無所謂图贸;
??????7)token就是令牌蹂季,比如授權登錄一個程序時,token就是依據(jù)疏日,判斷用戶是否已經授權該軟件偿洁;cookie是寫在客戶端的一個txt文件,里面包括登錄信息之類的沟优,這樣下次登錄某個網(wǎng)站涕滋,就會自動調用cookie自動登錄用戶名,session和cookie差不多挠阁,只是session是寫在服務器端的文件宾肺,只需要在客戶端寫入cookie文件,session的狀態(tài)是存儲在服務器端侵俗,客戶端只有session_id锨用,而token的狀態(tài)是存儲在客戶端的;
??????8)對于session坡慌,每個瀏覽器只需要保存自己的session_id黔酥,而服務器需要保存所有用戶的session_id藻三,如果訪問服務器的用戶多了洪橘, 對于服務器來說是一個巨大的開銷 , 嚴重限制了服務器的擴展能力棵帽。比如說服務器用兩個機器組成了一個集群熄求, 小F通過機器A登錄了系統(tǒng), 那session_id會保存在機器A上逗概, 假設小F的下一次請求被轉發(fā)到機器B弟晚,但機器B并沒有小F的 session_id,有時候服務器會采用一點小伎倆即session sticky 逾苫,就是讓小F的請求一直粘連在機器A上卿城,但是如果機器A掛掉了,還是需要轉到機器B去铅搓,那么只好做session的復制了瑟押,把session_id 在兩個機器之間搬來搬去, 非常費勁星掰。
??????token:如果不保存這些session_id, 就無法驗證客戶端發(fā)來的session_id是否合法多望;比如說嫩舟, 小F已經登錄了系統(tǒng),發(fā)給他一個令牌(token)怀偷, 里邊包含了小F的 user id家厌, 下一次小F 再次通過Http 請求訪問的時候, 把這個token 通過Http header 帶過來就可以了椎工,不過這和session_id沒有本質區(qū)別饭于,任何人都可以可以偽造, 想讓別人無法偽造晋渺,那就需要對數(shù)據(jù)做一個簽名镰绎, 比如HMAC-SHA256 算法,加上一個只有服務器自己才知道的密鑰對數(shù)據(jù)做一個簽名木西,把這個簽名和數(shù)據(jù)一起作為token畴栖,由于密鑰別人不知道,就無法偽造token了八千;
??????這個token服務器端不保存吗讶, 當小F把這個token發(fā)過來的時候,服務器再用同樣的 HMAC-SHA256 算法和同樣的密鑰恋捆,對數(shù)據(jù)再計算一次簽名照皆,和token中的簽名做比較,如果相同則知道小F已經登錄過了沸停,并且可以直接取到小F的user id膜毁,如果不相同,數(shù)據(jù)部分肯定被人篡改過即為非法認證愤钾;
??????token中的數(shù)據(jù)是明文保存的(雖然會做下編碼瘟滨,但那不是加密),還是可以被別人看到的能颁,所以不能在其中保存像密碼這樣的敏感信息杂瘸,但如果一個人的token 被別人偷走了,也會認為小偷就是合法用戶伙菊,這其實和session_id被別人偷走是一樣的败玉,這樣一來就不保存session_id了,只是生成token镜硕,然后驗證token运翼,用CPU計算時間獲取了session存儲空間。
6. webStorage
6.1. LocalStorage
??????持久化的存儲方式兴枯,如果不手動清除血淌,數(shù)據(jù)就永遠不會過期,采用key-value的方式存儲數(shù)據(jù)念恍,底層數(shù)據(jù)接口是sqlite六剥,按域名將數(shù)據(jù)分別保存到對應數(shù)據(jù)庫文件里晚顷,它能保存更大的數(shù)據(jù)(5M),同時保存的數(shù)據(jù)不會再發(fā)送給服務器疗疟,避免帶寬浪費该默;
6.2. sessionStorage
??????和服務器端使用的session類似,是一種會話級別的緩存策彤,關閉瀏覽器數(shù)據(jù)會被清除栓袖,不過有點特別的是它的作用域是窗口級別的,也就是說不同窗口間的sessionStorage數(shù)據(jù)不能共享店诗;
6.3. sessionStorage和LocalStorage的區(qū)別
??????sessionStorage用于本地存儲一個會話(session)中的數(shù)據(jù)裹刮,這時數(shù)據(jù)只有在同一個會話中的頁面才能訪問并且當會話結束后數(shù)據(jù)也隨之銷毀,因此sessionStorage不是一種持久化的本地存儲庞瘸,僅僅是會話級別的存儲捧弃,當用戶關閉瀏覽器窗口時,數(shù)據(jù)立馬會被刪除擦囊;localStorage用于持久化的本地存儲违霞,除非主動刪除數(shù)據(jù),否則數(shù)據(jù)是永遠不會過期的瞬场。
6.4. cookie和webStorage的區(qū)別
6.4.1. cookie的特點
??????cookie是指某些網(wǎng)站為了辨別用戶身份而存儲在用戶本地終端上的數(shù)據(jù)买鸽;
???1)內存cookie:由瀏覽器維護,保存在內存中贯被,瀏覽器關閉就消失眼五,存在時間短;
???2)硬盤cookie:保存在硬盤中彤灶,除非用戶手工清朝或到了過期時間看幼,一般不會刪除;
???3)用途:服務器可以設置或讀取cookie中包含的信息枢希,借此維護用戶跟服務器會話中的狀態(tài)桌吃,因為HTTP協(xié)議是無狀態(tài)的朱沃,就是說服務器不知道用戶上一次做了什么苞轿,為實現(xiàn)交互,就用cookie來記錄逗物;
???比如搬卒,網(wǎng)上購物,用戶選購了一個商品翎卓,服務器在向用戶發(fā)送網(wǎng)頁時還發(fā)送一段記錄商品信息的cookie契邀,當用戶訪問另一個頁面,瀏覽器會把cookie發(fā)送給服務器端失暴,于是服務器就知道用戶選購了什么坯门;
???登錄網(wǎng)站勾選“下次自動登錄”微饥,那么下次訪問就不用再輸入密碼等信息,這是因為在第一次登錄時古戴,如果勾選了自動登錄欠橘,那么服務器發(fā)送包含登錄憑據(jù)(用戶加密碼的某種加密形式)的cookie到用戶的硬盤上,第二次登錄時现恼,瀏覽器就會發(fā)送該cookie肃续,服務器驗證憑據(jù),就不用再次輸入密碼等叉袍;
???5)Web Storage是為了更大容量存儲設計的始锚,Cookie的大小是受限的,并且每次請求一個新的頁面的時候Cookie都會被發(fā)送過去喳逛,這樣無形中浪費了帶寬瞧捌,另外cookie還需要指定作用域,不可以跨域調用润文;cookie數(shù)據(jù)始終在同源的http請求中攜帶(即使不需要)察郁,即cookie在瀏覽器和服務器間來回傳遞,而sessionStorage和localStorage不會自動把數(shù)據(jù)發(fā)給服務器转唉,僅在本地保存皮钠,cookie數(shù)據(jù)還有路徑(path)的概念,可以限制cookie只屬于某個路徑下赠法;
6.4.2. webStorage的特點
??????webStorage擁有setItem
麦轰、getItem
、removeItem
砖织、clear
等方法款侵,不像cookie需要前端開發(fā)者自己封裝setCookie
,getCookie
侧纯;
??????sessionStorage與頁面 js 數(shù)據(jù)對象的區(qū)別:頁面中一般的 js 對象或數(shù)據(jù)的生存期是僅在當前頁面有效新锈,因此刷新頁面或轉到另一頁面這樣的重新加載頁面的情況,數(shù)據(jù)就不存在了眶熬,而sessionStorage 只要同源的同窗口(或tab)中妹笆,刷新頁面或進入同源的不同頁面,數(shù)據(jù)始終存在娜氏。也就是說只要這個瀏覽器窗口沒有關閉拳缠,加載新頁面或重新加載,數(shù)據(jù)仍然存在贸弥;
??????webStorage 有兩種機制:
??????1)sessionStorage 為每一個給定的源維持一個獨立的存儲區(qū)域窟坐,該存儲區(qū)域在頁面會話期間可用(瀏覽器是打開狀態(tài),包括頁面重載和恢復);localStorage 同上哲鸳,但瀏覽器關閉之后臣疑,重新打開數(shù)據(jù)還是存在;
??????2)webStorage 支持事件通知機制徙菠,可以將數(shù)據(jù)更新的通知發(fā)送給監(jiān)聽者朝捆,WebStorage 的 api 接口使用更方便;
6.4.3. webStorage和cookie的區(qū)別
6.4.3.1. 生命周期
??????cookie:可設置失效時間懒豹,沒有設置的話芙盘,默認是關閉瀏覽器后失效;
??????localStorage:除非被手動清除脸秽,否則將會永久保存儒老;
??????sessionStorage: 僅在當前網(wǎng)頁會話下有效,關閉頁面或瀏覽器后就會被清除记餐;
6.4.3.2. 存放數(shù)據(jù)大小
??????cookie:4KB左右驮樊;
??????localStorage和sessionStorage:可以保存5MB的信息;
6.4.3.3. http請求
??????cookie:每次都會攜帶在HTTP頭中片酝,如果使用cookie保存過多數(shù)據(jù)會帶來性能問題囚衔;
??????localStorage和sessionStorage:僅在客戶端(即瀏覽器)中保存,不參與和服務器的通信雕沿;
6.4.3.4. 易用性
??????cookie:需要程序員自己封裝练湿,源生的Cookie接口不友好;
??????localStorage和sessionStorage:源生接口可以接受审轮,亦可再次封裝來對Object和Array有更好的支持肥哎;
6.4.3.5. 應用場景:
??????從安全性來說,因為每次http請求都會攜帶cookie信息疾渣,這樣無形中浪費了帶寬篡诽,所以cookie應該盡可能少的使用,另外cookie還需要指定作用域榴捡,不可以跨域調用杈女,限制比較多。但是用來識別用戶登錄來說吊圾,cookie還是比webStorage更好用达椰,其他情況下,可以使用webStorage街夭,就用webStorage;
??????webStorage在存儲數(shù)據(jù)的大小上面秒殺了cookie;
??????localStorage和sessionStorage唯一的差別一個是永久保存在瀏覽器里面砰碴,一個是關閉網(wǎng)頁就清除了信息躏筏,localStorage可以用來跨頁面?zhèn)鬟f參數(shù)板丽,sessionStorage用來保存一些臨時的數(shù)據(jù),防止用戶刷新頁面之后丟失了一些參數(shù);
6.4.3.6. 瀏覽器支持情況
??????localStorage和sessionStorage是html5才應用的新特性,可能有些瀏覽器并不支持埃碱。
6.4.3.7. 數(shù)據(jù)存放處
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>本地存儲</title>
</head>
<body>
<div>打開控制臺查看console</div>
<p><a target="_blank" >查看代碼文件</a></p>
<script>
cookieFn();
strogeFn();
function cookieFn() {
var dataCookie='110';
document.cookie = 'token' + "=" +dataCookie;//直接設置cookie
function getCookie(name) { //獲取指定名稱的cookie值
// (^| )name=([^;]*)(;|$),match[0]為與整個正則表達式匹配的字符串猖辫,match[i]為正則表達式捕獲數(shù)組相匹配的數(shù)組;
var arr = document.cookie.match(new RegExp("(^| )"+name+"=([^;]*)(;|$)"));
if(arr != null) {
console.log(arr,'正則表達式捕獲數(shù)組相匹配的數(shù)組');
return unescape(arr[2]);
}
return null;
}
var cookieData=getCookie('token');
console.log(cookieData,'獲取指定名稱的cookie值');
function setTime() {
//存儲cookie值并且設置cookie過期時間
var date=new Date();
var expiresDays=10;//設置十天過期
date.setTime(date.getTime()+expiresDays*24*3600*1000);
document.cookie="userId=828; expires="+date.toGMTString();
console.log(document.cookie,'存儲cookie值并且設置cookie過期時間');
}
setTime();
function delCookie(cookieName1) {
//刪除cookie
var date2=new Date();
date2.setTime(date2.getTime()-10001);//把時間設置為過去的時間砚殿,會自動刪除
document.cookie= cookieName1+"=v; expires="+date2.toGMTString();
console.log(document.cookie,'刪除cookie');
}
delCookie('userId');
}
function strogeFn() {
var name='sessionData';
var num=120;
sessionStorage.setItem(name,num);//存儲數(shù)據(jù)
sessionStorage.setItem('value2',119);
let dataAll=sessionStorage.valueOf();//獲取全部數(shù)據(jù)
console.log(dataAll,'獲取全部數(shù)據(jù)');
var dataSession=sessionStorage.getItem(name);//獲取指定鍵名數(shù)據(jù)
var dataSession2=sessionStorage.sessionData;//sessionStorage是js對象啃憎,也可以使用key的方式來獲取值
console.log(dataSession,dataSession2,'獲取指定鍵名數(shù)據(jù)');
sessionStorage.removeItem(name); //刪除指定鍵名數(shù)據(jù)
console.log(dataAll,'獲取全部數(shù)據(jù)1');
sessionStorage.clear();//清空緩存數(shù)據(jù):localStorage.clear();
console.log(dataAll,'獲取全部數(shù)據(jù)2');
}
</script>
</body>
</html>
6.4.4. webStorage和cookie的操作異同
6.4.4.1. cookie的操作
// 保存cookie
var dataCookie='110';
document.cookie = 'token' + "=" +dataCookie;
// 獲取指定名稱的cookie
function getCookie(name) { //獲取指定名稱的cookie值
// (^| )name=([^;]*)(;|$),match[0]為與整個正則表達式匹配的字符串,match[i]為正則表達式捕獲數(shù)組相匹配的數(shù)組似炎;
var arr = document.cookie.match(new RegExp("(^| )"+name+"=([^;]*)(;|$)"));
if(arr != null) {
console.log(arr);
return unescape(arr[2]);
}
return null;
}
var cookieData=getCookie('token'); //cookie賦值給變量辛萍。
6.4.4.2. webStorage的操作
var name='sessionData';
var num=120;
sessionStorage.setItem(name,num);//存儲數(shù)據(jù)
sessionStorage.setItem('value2',119);
let dataAll=sessionStorage.valueOf();//獲取全部數(shù)據(jù)
console.log(dataAll,'獲取全部數(shù)據(jù)');
var dataSession=sessionStorage.getItem(name);//獲取指定鍵名數(shù)據(jù)
var dataSession2=sessionStorage.sessionData;//sessionStorage是js對象,也可以使用key的方式來獲取值
console.log(dataSession,dataSession2,'獲取指定鍵名數(shù)據(jù)');
sessionStorage.removeItem(name); //刪除指定鍵名數(shù)據(jù)
console.log(dataAll,'獲取全部數(shù)據(jù)1');
sessionStorage.clear();//清空緩存數(shù)據(jù):localStorage.clear();
console.log(dataAll,'獲取全部數(shù)據(jù)2');