談?wù)凜ookie與Storage

聊Cookie

1. Cookie是怎么出現(xiàn)的傻铣?

  • 可由服務(wù)端設(shè)置,也可由客戶端設(shè)置漆枚,如果兩端都沒有設(shè)置則不存在Cookie
  • 來源于客戶端設(shè)置竞川,即通過document.cookie = 'xxx=yyy'的形式
  • 來源于服務(wù)端設(shè)置,操作如下:
    1. 瀏覽器發(fā)送HTTP請(qǐng)求
    2. 服務(wù)器收到請(qǐng)求酒唉,設(shè)置Cookie并在響應(yīng)頭添加Set-Cookie 字段
    3. 瀏覽器收到響應(yīng)后保存Cookie
    4. 下次請(qǐng)求該服務(wù)器都通過Cookie字段將Cookie發(fā)送給服務(wù)器

2. Cookie格式

Cookie以鍵值對(duì)形式的字符串保存矩桂,即key=value,例如name=cookie_name黔州。除了Name/Value外耍鬓,Cookie字符串值中還存在許多特殊的key值,具體如下:

  • Path:指定一個(gè)URL路徑流妻,如果沒有定義則使用當(dāng)前文檔位置的路徑牲蜀。如果設(shè)置了path=/docs,那么/test路徑下不會(huì)攜帶Cookie首部绅这,/docs/test則會(huì)攜帶
  • Domain:指定可以送達(dá)的域名涣达,如果沒有指定,默認(rèn)為當(dāng)前文檔位置的路徑的域名部分。這里要注意的是度苔,不能跨域設(shè)置Cookie匆篓,如果在a.com下設(shè)置此屬性為b.com是無效的。DomainPath一起為Cookie指定作用域寇窑,即在哪些URL下是有效的鸦概。
  • Expires:用于設(shè)置Cookie的過期時(shí)間,默認(rèn)值為Session甩骏,表示為會(huì)話性Cookie窗市。
  • Max-Age:設(shè)置到失效的時(shí)長(zhǎng),有三種情況如下饮笛。當(dāng)與Expires屬性并存咨察,優(yōu)先級(jí)高于Expires
    • 正數(shù):持久化緩存直到過期
    • 負(fù)數(shù):會(huì)話性Cookie
    • 0:立即刪除
  • Secure:表示Cookie只通過https協(xié)議傳輸。
  • HTTPOnly:增刪改查只由服務(wù)端操作福青,客戶端腳本不得操作摄狱。
  • SameSite:可以讓 Cookie 在跨站請(qǐng)求時(shí)不會(huì)被發(fā)送,從而可以阻止跨站請(qǐng)求偽造攻擊(CSRF)无午。最近很熱門媒役, 因?yàn)镃hrome80 版本中默認(rèn)屏蔽了第三方的 Cookie。包含以下可選的三個(gè)值:
    • Strict:僅發(fā)送與當(dāng)前URL相同站點(diǎn)的Cookie
    • Lax:允許部分第三方請(qǐng)求攜帶Cookie
    • None:無論是否跨站都會(huì)攜帶Cookie

3. 操作Cookie如何清除Cookie

操作時(shí)需要注意的是宪迟,要將值轉(zhuǎn)換為字符串刊愚,最好通過encodeURIComponent。另外賦值Cookie時(shí)踩验,每一次都是一條新的記錄(key值相同會(huì)覆蓋)鸥诽。

  // 瀏覽器設(shè)置
  document.cookie = 'name=cookie';
  document.cookie;  //name=cookie

  //再次設(shè)置時(shí),值會(huì)追加在后面
  document.cookie = 'age=18';
  document.cookie;  //name=cookie; age=18

  //相同key值的設(shè)置
  document.cookie = 'name=cookie_again';
  document.cookie;  //name=document.cookie; age=18

  //一次寫入多個(gè)key/value
  document.cookie = 'name=cookie;age=18'
  document.cookie  //name=cookie箕憾,并不支持一次寫入多個(gè)

  //設(shè)置特殊屬性
  document.cookie = 'name=cookie;max-age=60000';  //成功

  //單獨(dú)設(shè)置特殊屬性
  document.cookie = 'max-age=6000';
  document.cookie;  //max-age=6000牡借,單獨(dú)設(shè)置會(huì)轉(zhuǎn)化為key/value

4. Cookie的類別?

Cookie根據(jù)作用不同袭异,分為以下兩類:

  • 會(huì)話性Cookie:當(dāng)Expires/Max-Age屬性缺省時(shí)钠龙,表現(xiàn)為會(huì)話性。此時(shí)值保存在客戶端內(nèi)存中御铃,當(dāng)關(guān)閉瀏覽器時(shí)失效碴里。值得注意的是,有些瀏覽器會(huì)有會(huì)話恢復(fù)功能上真,這種情況下就算關(guān)閉瀏覽器咬腋,會(huì)話Cookie依然會(huì)被保留下來。
  • 持久性Cookie:持久性Cookie與會(huì)話性不同睡互,會(huì)保存在硬盤中根竿,直至過期或被清除陵像。持久性Cookie一般是客戶端用來緩存用戶數(shù)據(jù)。

5. Cookie有什么特點(diǎn)/限制寇壳?

  • 管理會(huì)話狀態(tài)
  • 瀏覽器行為跟蹤
  • 最大容量4kb
  • 每次請(qǐng)求時(shí)會(huì)附帶在頭部發(fā)送給服務(wù)器醒颖,會(huì)增加請(qǐng)求的大小
  • 安全問題,好吧壳炎,存在瀏覽器的都不怎么安全

聊Storage

  1. 有l(wèi)ocalStorage與sessionStorage兩種泞歉,區(qū)別在于sessionStorage是會(huì)話性緩存,在當(dāng)前標(biāo)簽頁關(guān)閉(或?yàn)g覽器關(guān)閉)后會(huì)被清除匿辩。而localStorage是持久性緩存疏日,只要不手動(dòng)清除可一直保留。
  2. 限制
    • 大腥龊骸:一般瀏覽器為5M左右,網(wǎng)上有一部分資料說微信等瀏覽器只有2.5M涕滋,于是用http://dev-test.nemikor.com/web-storage/support-test/這個(gè)網(wǎng)站測(cè)試了一下微信webview睬辐,顯示的依然是5M左右。問題來了宾肺,如果超出使用大小限制會(huì)如何溯饵?答案是會(huì)拋出錯(cuò)誤QUOTA_EXCEEDED_ERR

      取自網(wǎng)上資源

    • 跨域:瀏覽器同源策略,只可以訪問同源下的Storage锨用,而sessionStorage在此基礎(chǔ)上更進(jìn)一步丰刊,只能訪問同一標(biāo)簽頁中的Storage,同一頁面內(nèi)嵌的同源iframe的Storage也可以訪問增拥。

    • 是否可用:目前的兼容性是很好的啄巧,但有些情況需要一定的手段去檢測(cè)是否可用,比如在隱身/無痕模式下的safari掌栅,存在localStorage對(duì)象秩仆,但無進(jìn)行setItem操作。

選擇使用哪種

成熟的人不做選擇猾封,成熟的人都想要??澄耍。在項(xiàng)目中應(yīng)當(dāng)結(jié)合實(shí)際的需求進(jìn)行取舍,比如:

  • 需要兼容到極低版本的瀏覽器(懂的都懂)晌缘,那么肯定使用Cookie了
  • 少量的用戶狀態(tài)數(shù)據(jù)齐莲,且有會(huì)話性Cookie需求,Cookie會(huì)更好
  • 大容量的存取磷箕,選Storage
  • 需要持久化緩存选酗,localStorage吧
  • 只需要在當(dāng)前頁面使用的數(shù)據(jù),sessionStorage搞一個(gè)
  • ……

localStorage如何實(shí)現(xiàn)與Cookie一樣的過期功能

localStorage本身并沒有緩存過期的實(shí)現(xiàn)岳枷,所以有需要的話開發(fā)人員自己去擴(kuò)展星掰。思路也很簡(jiǎn)單多望,在設(shè)置緩存時(shí)傳入過期時(shí)間,以及記錄設(shè)置時(shí)的初始時(shí)間戳氢烘,這樣在獲取緩存時(shí)即可通過對(duì)比當(dāng)前時(shí)間查看是否已過期怀偷,簡(jiǎn)單的實(shí)現(xiàn)如下:

const $local = {
    /**
     * 設(shè)置緩存
     * @param {string} key
     * @param {*} value
     * @param {number} expires 多少毫秒后過期
     */
    set: (key, value, expires) => {
        localStorage.setItem(key, JSON.stringify({
            value: value,
            expires: expires,
            startTime: Date.now()  //緩存設(shè)置時(shí)間
        }))
    },

    /**
     * 獲取緩存
     * @param {string} key
     */
    get: key => {
        let cache = localStorage.getItem(key);

        //無緩存值
        if (!cache) {
            return undefined
        }

        let {expires, startTime, value} = JSON.parse(cache);

        //已過期
        if (expires && Date.now() - startTime > expires) {
            return undefined
        }

        return value
    }
} 

如何確定是否localStorage是否可用呢?

以下是大致的思想播玖,當(dāng)然在項(xiàng)目中會(huì)把用成熟的庫來進(jìn)行操作椎工,推薦store.js等庫。

  //檢測(cè)是否存在localStorage
  if ('localStorage' in window) {
      try {
          //可用
          localStorage.setItem('incognito.test', '1');
      } catch (error) {
          //不可用
      }
  } else {
      //不可用
  }

同源多頁面通訊

這也是一個(gè)比較常見的問題蜀踏,實(shí)現(xiàn)的方法有很多维蒙,其中就包括使用StorageEvent來實(shí)現(xiàn)。什么是StorageEvent呢果覆?其實(shí)就是一個(gè)事件颅痊,當(dāng)Storage被設(shè)置時(shí)會(huì)觸發(fā),注意點(diǎn)如下局待。利用這個(gè)事件即可實(shí)現(xiàn)同源多頁面通訊

  • 當(dāng)前頁面Storage改變不會(huì)觸發(fā)此事件斑响,非當(dāng)前頁(同源)會(huì)收到此事件。實(shí)現(xiàn)如下
    window.addEventListener('storage', function (e) {
      //在此進(jìn)行操作
    });
    
  • 設(shè)置的key值沒有改變也不會(huì)觸發(fā)此事件
    //第一次觸發(fā)事件
    window.localStorage.setItem('test', '123');
    //值沒有改變钳榨,第二次不觸發(fā)
    window.localStorage.setItem('test', '123');
    

結(jié)語??

回顧了下Cookie與Storage舰罚,有部分是之前沒有注意到的,比如突破Storage存儲(chǔ)限制后會(huì)拋出錯(cuò)誤薛耻;在使用localStorage营罢,并以持久化存儲(chǔ)為目標(biāo)時(shí)并不絕對(duì)可靠,例如在手機(jī)瀏覽器/webview中饼齿,系統(tǒng)內(nèi)存不足時(shí)會(huì)自動(dòng)清理緩存文件饲漾,這些都是平時(shí)沒有注意到的地方。

部分內(nèi)容來自以下blog

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末缕溉,一起剝皮案震驚了整個(gè)濱河市能颁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌倒淫,老刑警劉巖伙菊,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異敌土,居然都是意外死亡镜硕,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門返干,熙熙樓的掌柜王于貴愁眉苦臉地迎上來兴枯,“玉大人,你說我怎么就攤上這事矩欠〔破剩” “怎么了悠夯?”我有些...
    開封第一講書人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)躺坟。 經(jīng)常有香客問我沦补,道長(zhǎng),這世上最難降的妖魔是什么咪橙? 我笑而不...
    開封第一講書人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任夕膀,我火速辦了婚禮,結(jié)果婚禮上美侦,老公的妹妹穿的比我還像新娘产舞。我一直安慰自己,他們只是感情好菠剩,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開白布易猫。 她就那樣靜靜地躺著,像睡著了一般具壮。 火紅的嫁衣襯著肌膚如雪准颓。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,165評(píng)論 1 299
  • 那天嘴办,我揣著相機(jī)與錄音,去河邊找鬼买鸽。 笑死涧郊,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的眼五。 我是一名探鬼主播妆艘,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼看幼!你這毒婦竟也來了批旺?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤诵姜,失蹤者是張志新(化名)和其女友劉穎汽煮,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體棚唆,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡暇赤,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了宵凌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鞋囊。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖瞎惫,靈堂內(nèi)的尸體忽然破棺而出溜腐,到底是詐尸還是另有隱情译株,我是刑警寧澤,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布挺益,位于F島的核電站歉糜,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏矩肩。R本人自食惡果不足惜现恼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望黍檩。 院中可真熱鬧叉袍,春花似錦、人聲如沸刽酱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽棵里。三九已至润文,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間殿怜,已是汗流浹背典蝌。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留头谜,地道東北人骏掀。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像柱告,于是被迫代替她去往敵國(guó)和親截驮。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容