我們來聊聊Cookie、Session和Storage的那些事

導語

我們在做項目的時候,經常把Cookie和Session掛在嘴邊,可實際對于他們了解的也是很少,只是會使用,但這遠遠不夠,熟練的掌握他們的特性才能把項目做的更好。下面我們就來認識一下他們吧!

先來了解一下Cache

Cache表示數據緩存,合理的設置cache,它可以幫助我們提高訪問速度,減少請求(在緩存有效期內直接讀取Cache文件),減少文件從服務器直接拉取文件(緩存過期后,請求服務器器檢查文件是否被更改,如沒有被更改則返回304然后讀取Cache);

Cache的數據一般是服務器上不經常變動的數據,如圖片、某些數據js、html、php等;如果是經常變動的數據一般是不被緩存的,沒有意義;如果把一個經常變動的文件緩存起來的話,沒有多大意義。

讀取Cache的過程

首先檢查文件設置的緩存是否過期:

  • 如果過期了,則會重新發送請求到服務器,檢查該文件是否有被更新,如果沒有被更新,則服務器會返回304 Not Modified,表示服務器上該文件沒有被更新,用戶發起的對該文件請求則會直接從本地cache讀取;如果服務上文件被更新了,則服務器會返回新的文件,此時http返回碼為200 ok,更新緩存。

  • 如果沒有過期,則會直接讀取本地cache文件,不再發起http請求;

在瀏覽器的控制臺的Network,我們可以看到一些文件的Headers,我們來說說其中的一些頭部設置的作用:

Responese Headers

access-control-allow-origin:*
cache-control:max-age=691200
content-length:0
date:Sun, 22 Apr 2018 03:25:41 GMT
etag:"5ad8603c-214cb"
expires:Fri, 27 Apr 2018 13:33:04 GMT
server:marco/2.0
status:304
via:T.3.H, M.ctn-fj-foc-007
x-request-id:30e1ceac71122f15ed9144c272406682

Request Headers

:authority:static.segmentfault.com
:method:GET
:path:/v-5ad86038/3rd/assets.js
:scheme:https
accept:*/*
accept-encoding:gzip, deflate, sdch, br
accept-language:zh-CN,zh;q=0.8
cache-control:max-age=0
if-modified-since:Thu, 19 Apr 2018 09:24:12 GMT
if-none-match:W/"5ad8603c-214cb"
origin:https://segmentfault.com
referer:https://segmentfault.com/user/settings?tab=notify
user-agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36 Core/1.53.5006.400 QQBrowser/9.7.13080.400
  • expires

    expires是HTTP/1.0控制網頁緩存的字段,表示服務器返回該請求結果緩存的到期時間,即再次發起該請求時,如果客戶端的時間小于Expires的值時,直接使用緩存結果;expires=當前服務器date+緩存有效時間;時間格式為GTM,是一個絕對值。

  • cache-control

    用戶控制http的緩存,max-age表示客戶端可以接收生存期不大于指定時間(以秒為單位)的響應;max-age=0;表示每次請求該文件時,都需要請求服務器檢查文件在上一次被緩存時有無修改過;max-age=10;表示10s內再次對該文件發起請求則不需要向服務器發起請求讀取文件,直接讀取本地cache文件;

    在HTTP/1.1中,Cache-Control是最重要的規則,主要用于控制網頁緩存,主要取值為:

    • public:所有內容都將被緩存(客戶端和代理服務器都可緩存)

    • private:所有內容只有客戶端可以緩存,Cache-Control的默認取值

    • no-cache:客戶端緩存內容,但是是否使用緩存則需要經過協商緩存來驗證決定

    • no-store:所有內容都不會被緩存,即不使用強制緩存,也不使用協商緩存

    • max-age=xxx (xxx is numeric):緩存內容將在xxx秒后失效,是一個相對值

    由于Cache-Control的優先級比expires,那么直接根據Cache-Control的值進行緩存,意思就是說在600秒內再次發起該請求,則會直接使用緩存結果,強制緩存生效。

    注:在無法確定客戶端的時間是否與服務端的時間同步的情況下,Cache-Control相比于expires是更好的選擇,所以同時存在時,只有Cache-Control生效。

以上只是簡單的了解一下Cache,更深入的了解瀏覽器的緩存機制,可以看看這篇文章-->徹底理解瀏覽器的緩存機制,講得深入,看完會對你有很大的幫助。

Cookie

Cookie是客戶端存儲數據的一個一種選項

當我們向服務器發送任意的HTTP請求的時候,服務器會返回一個帶有Set-Cookie的HTTP響應頭返回給瀏覽器,其中包含一些會話信息。這種響應頭可能如下:

// Response Headers 響應頭

HTTP/1.1 200 OK
Server: nginx/1.10.1
Date: Sun, 22 Apr 2018 06:16:14 GMT
Content-Type: text/html
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Set-Cookie: SID=t65ln3kllu7ujutldk4hcota05; path=/
Content-Encoding: gzip

這個響應頭設置SID為名稱,t65ln3kllu7ujutldk4hcota05為值的一個Cookie。

如果用戶不是第一次訪問,即:本地已經存在cookie,則在發送請求時會將cookie一并發給服務器,服務器收到請求之后會作出相應處理,返回對應的信息;這種請求頭可能如下:

// request Headers 請求頭

Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:zh-CN,zh;q=0.8
Connection:keep-alive
Cookie: SID=t65ln3kllu7ujutldk4hcota05

Cookie的設置

設置方式為:

document.cookie="name=value;domain=域名;path=/;expires=過期時間;secure"

其中name和value是必須,其他為可選;name和value都需要經過URL編碼--encodeURIComponent()

現在介紹一下Cookie的構成:

  • name :一個唯一確定Cookie的名稱,不區分大小寫,獲取Cookie是根據name來查找

  • value:存儲在Cookie中的字符串值

  • domain:Cookie對于哪個域有效,比如domain="aa.qq.com",那么qq.com就不可以讀取該Cookie,如果沒有設置,會默認該請求來自當前域。

  • path:對于指定域中的哪個路徑。比如path="/book/",那么對于www.aa.qq.com/cc/的請求就不能發送Cookie

  • expires:Cookie過期時間,這個值是GMT格式的日期

  • secure:設置這個標志后,Cookie只有在SSL鏈接的時候才會發送給服務器,比如https://www.aa.qq.com可以,而http://www.aa.qq.com就不行

Cookie的缺點

  • Cookie在每個瀏覽器以及版本的數量都不同

    • IE6一下版本每個域名最多20個
    • IE7以上的版本每個域名最多50個
    • FireFox每個域名最多50個
    • Opera每個域名最多30個
    • Safari和Chrome沒有硬性規定,應該是有一個極限的
  • 大小受限,一般是在4k左右,最好別超過4k

  • 用戶可以操作禁用cookie,使功能受限

  • 安全性較低

  • 有些狀態不可能保存在客戶端

  • 每次訪問都要傳送cookie給服務器,浪費帶寬。

  • cookie數據有路徑(path)的概念,可以限制cookie只屬于某個路徑下。

瀏覽器提供設置Cookie方法比較簡陋,操作會比較麻煩,我們可以自己動手封裝一個

class CookieUtil{
    constructor(){

    }

    get(name){
        var cookies=document.cookie.split(";");
        var curCookie;
        for(var i=0;i<cookies.length;i++){
            curCookie=cookies[i].split("=");
            if(decodeURIComponent(curCookie[0])===name){
                return decodeURIComponent(curCookie[1])
            }

        }
        return null;
    }
    set(name,value,expires,domain,path,secure){
        if(!name&&!value){
            return
        }
        var cookieStr=encodeURIComponent(name)+"="+encodeURIComponent(value);
        if(expires && (expires instanceof Date)){
            cookieStr+=";expires="+expires.toGMTString();
        }

        if(path){
            cookieStr+=";path="+path
        }
        if(domain){
            cookieStr+=";domain="+domain
        }
        if(secure){
            cookieStr+=";secure"
        }
        document.cookie=cookieStr;
    }

    delete(name,domain,path,secure){
        this.set(name,"",new Date(0),domain,path,secure)
    }
}

Session

Session是保存在服務端的,通過類似與Hashtable的數據結構來保存,能支持任何類型的對象(session中可含有多個對象)

Session機制

當服務器收到請求需要創建session對象時,首先會檢查客戶端請求中是否包含sessionid。如果有sessionid,服務器將根據該id返回對應session對象。如果客戶端請求中沒有sessionid,服務器會創建新的session對象,并把sessionid在本次響應中返回給客戶端。通常使用cookie方式存儲sessionid到客戶端,在交互中瀏覽器按照規則將sessionid發送給服務器。如果用戶禁用cookie,則要使用URL重寫,可以通過response.encodeURL(url)進行實現;API對encodeURL的約束為:當瀏覽器支持Cookie時,url不做任何處理;當瀏覽器不支持Cookie的時候,將會重寫URL將SessionID拼接到訪問地址后。

Session的優點

  • 大小沒有限制

  • session的安全性大于cookie,原因如下:

    • sessionID存儲在cookie中,若要攻破session首先要攻破cookie

    • sessionID是要有人登錄,或者啟動session_start(php中的方法)才會有,所以攻破cookie也不一定能得到sessionID

    • 第二次啟動session_start后,前一次的sessionID就是失效了,session過期后,sessionID也隨之失效。

    • sessionID是加密的

Session的缺點

  • Session保存的東西越多,就越占用服務器內存,對于用戶在線人數較多的網站,服務器的內存壓力會比較大。

  • 依賴于cookie(sessionID保存在cookie),如果禁用cookie,則要使用URL重寫,不安全

  • 創建Session變量有很大的隨意性,可隨時調用,不需要開發者做精確地處理,所以,過度使用session變量將會導致代碼不可讀而且不好維護。

Storage

WebStorage目的是克服由cookie所帶來的一些限制,當數據需要被嚴格控制在客戶端時,不需要持續的將數據發回服務器。

Webstorage的兩個主要目標:

  • 提供一種在cookie之外存儲會話數據的路徑。
  • 提供一種存儲大量可以跨會話存在的數據的機制。

HTML5的WebStorage提供了兩種API:localStorage(本地存儲)和sessionStorage(會話存儲)。

  • 生命周期

    • localStorage:localStorage的生命周期是永久的,關閉頁面或瀏覽器之后localStorage中的數據也不會消失。localStorage除非主動刪除數據,否則數據永遠不會消失。

    • sessionStorage的生命周期是在僅在當前會話下有效。sessionStorage引入了一個“瀏覽器窗口”的概念,sessionStorage是在同源的窗口中始終存在的數據。只要這個瀏覽器窗口沒有關閉,即使刷新頁面或者進入同源另一個頁面,數據依然存在。但是sessionStorage在關閉了瀏覽器窗口后就會被銷毀。同時獨立的打開同一個窗口同一個頁面,sessionStorage也是不一樣的。

  • 存儲大小:

    • localStorage和sessionStorage的存儲數據大小一般都是:5MB
  • 存儲位置:

    • localStorage和sessionStorage都保存在客戶端,不與服務器進行交互通信。
  • 存儲內容類型:

    • localStorage和sessionStorage只能存儲字符串類型,對于復雜的對象可以使用ECMAScript提供的JSON對象的stringify和parse來處理
  • 獲取方式:

    • localStorage:window.localStorage;;
    • sessionStorage:window.sessionStorage;。
  • 應用場景:

    • localStoragese:常用于長期登錄(+判斷用戶是否已登錄),適合長期保存在本地的數據。
    • sessionStorage:敏感賬號一次性登錄;

WebStorage的優點:

  • 存儲空間更大:

    • cookie為4KB,而WebStorage是5MB;
  • 節省網絡流量:

    • WebStorage不會傳送到服務器,存儲在本地的數據可以直接獲取,也不會像cookie一樣美詞請求都會傳送到服務器,所以減少了客戶端和服務器端的交互,節省了網絡流量;
  • 對于那種只需要在用戶瀏覽一組頁面期間保存而關閉瀏覽器后就可以丟棄的數據,sessionStorage會非常方便;

  • 快速顯示:

    • 有的數據存儲在WebStorage上,再加上瀏覽器本身的緩存。獲取數據時可以從本地獲取會比從服務器端獲取快得多,所以速度更快;
  • 安全性:

    • WebStorage不會隨著HTTP Header發送到服務器端,所以安全性相對于cookie來說比較高一些,不會擔心截獲,但是仍然存在偽造問題;
  • WebStorage提供了一些方法,數據操作比cookie方便;

    • setItem (key, value) —— 保存數據,以鍵值對的方式儲存信息。
    • getItem (key) —— 獲取數據,將鍵值傳入,即可獲取到對應的value值。
    • removeItem (key) —— 刪除單個數據,根據鍵值移除對應的信息。
    • clear () —— 刪除所有的數據
    • key (index) —— 獲取某個索引的key
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,505評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,556評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,463評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,009評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,778評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,218評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,436評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,969評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,795評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,993評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,229評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,659評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,917評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,687評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,990評論 2 374

推薦閱讀更多精彩內容