初次接觸 Cookie2(Session、LocalStorage、緩存等)

Session

因爲 Cookie 能夠被用戶篡改,不是一個安全的選擇,因此利用 Session 來解決防止用戶篡改的需求。css

Session 是屬於服務器的一個哈希表。api

在使用時,先定義一個sessions的哈希表,並生成一個隨機數當作當前用戶的sessionId,使用隨機數是爲了安全,這樣用戶就沒法經過篡改獲得其餘用戶正確的sessionId。接着將本應該放到 Cookie 裏的信息放到sessions[sessionId]裏面,存放到服務器上,並將sessionId經過Cookie傳給瀏覽器。瀏覽器

代碼實現以下:緩存

let sessionId = Math.random() * 100000; //此處更改爲其餘隨機方式
  sessions[sessionId] = { sign_in_email: email };
  response.setHeader('Set-Cookie',`sessionId=${sessionId}`);
複製代碼

經過這樣的操做,瀏覽器並不直接獲得用戶信息,而是給一個sessionId,服務器經過sessions匹配瀏覽器附帶的sessionId,獲得用戶信息。避免用戶經過篡改 Cookie 獲取其餘用戶的信息,並且sessionId是隨機生成的,徹底沒有規律可循,也就沒法僞造其餘用戶的sessionId安全

//hash 就是將 Cookie 裏的信息對象化獲得的
  let mySession = sessions[hash.sessionId];
  let email;
  if (mySession) {
    email = mySession.sign_in_email;
  }
複製代碼

這樣也能夠獲得當前用戶的信息,並且用戶還沒法僞形成其餘用戶。服務器

與 Cookie 的聯繫

  • Session 是利用 sessionId 基於 Cookie 實現的
  • Session 存儲在服務器中,其 sessionId 經過 Cookie 發送給瀏覽器
  • sessionId 隨 Cookie 在每次發生請求時發送給服務器

小結

  • sessionId 經過 Cookie 發送給瀏覽器
  • 瀏覽器在訪問服務器時,帶上這個 sessionId
  • 服務器有一塊內存存放了 sessionId-用戶信息 的鍵值對哈希表(sessions)
  • 這樣經過 sessionId 就能夠獲得對應用戶的信息

Session 太佔內存了,每個用戶都要存儲 (sessionId - 用戶信息),並且不能回收,當用戶量很大時,對硬件性能要求特別高。網絡

LocalStorage

LocalStorage 是存放在瀏覽器上的一個哈希表,且只能存放字符串(對於非字符串自動轉換成字符串,.toString())。session

瀏覽器有一個window.localstorage的 api,以下所示:dom

由於 LocalStorage 的值不隨頁面的關閉、刷新等發生變化,因此能夠用來存儲某些不須要隨頁面刷新而發生變化的值,持久化存儲。性能

經常使用場景爲:記錄有沒有提示過用戶某信息(不能用來記錄密碼)

特色

  • LocalStorage 與 HTTP 無關
  • 發生 HTTP 請求時不會帶上 LocalStorage 的值
  • 只有相同域名的頁面才能互相讀取 LocalStorage(沒有同源政策那麼嚴格)
  • 每一個域名的 LocalStorage 最大的存儲量爲 5Mb 左右(每一個瀏覽器各不同)
  • LocalStorage 永久有效,除非用戶手動清除

.setItem()

這是用來存儲 LocalStorage 數據的,用法以下

//語法
  localStorage.setItem('key','value')

  //實例
  localStorage.setItem('name','yyzcl')
複製代碼

非字符串的 keyvalue 會被轉換成字符串的形式,能夠存 JSON。

localStorage.setItem('yyzcl',{age: '18'})

  localStorage.setItem('yyzcl2',JSON.stringify({age: '18'}))
複製代碼

getItem()

用來讀取 LocalStorage 裏面的數據,用法以下:

//語法
  localStorage.getItem('key')

  //實例
  localStorage.getItem('yyzcl2')
複製代碼

.removeItem

用來刪除 LocalStorage 已經存儲的值,用法以下:

//語法
  localStorage.removeItem('key')

  //實例
  localStorage.removeItem('yyzcl')
複製代碼

.clear()

清空 LocalStorage 的值。

與 Cookie 的關係

  • Cookie 會隨 HTTP 請求發送給服務器,而 LocalStorage 不會
  • Cookie 的大小通常爲 4kb,而 LocalStorage 大小通常爲 5Mb(各瀏覽器不同)
  • Cookie 有有效期(可自行設置),LocalStorage 永久有效,除非用戶手動清除

SessionStorage

SessionStorage 與 LocalStorage 相似,也有 LocalStorage 那些 api等等特徵。可是,SessionStorage 在用戶關閉頁面(結束會話)時就會失效

HTTP 緩存

當咱們刷新頁面時,若是要從新請求一遍相同的資源,那就太消耗網絡和時間了。那麼有沒有辦法讓 HTTP 在請求相同資源的時候,不通過網絡鏈接服務器,直接從內存或硬盤中讀取以前下載的資源呢?有這麼幾種方法能夠實現。

Cache-Control

Cache-Control 通用消息頭被用於在 HTTP 請求和響應中經過指定指令來實現緩存機制。用法以下:

//語法
  Cache-Control: max-age=<seconds> //實例 response.setHeader('Cache-Control', 'max-age=30'); 複製代碼

若是咱們給一個頁面的 JS 文件響應設置了 Cache-Control 後,那麼在30秒內重複請求這個 JS 文件的話,瀏覽器會阻止這個請求,轉而從內存或硬盤中讀取這個 JS 文件。

這是首次加載的狀況。

而且在響應體中會有一個 Cache-Control: max-age=30 的信息,以下圖所示。

當瀏覽器在30秒以內再次請求這個 JavaScript 文件時,會是以下情形。

從圖中能夠看到,當設置了 Cache-Control ,而且在有效時間以內重複請求同一個文件,處理時間爲 0ms,也就是說瀏覽器根本沒有向服務器發出請求,而是從內存中讀取請求的文件。

JS、CSS 文件的緩存時間通常設置成一個很大的值,好比一年。

那麼期間要更新 JS、CSS 文件怎麼辦?

這裏只須要更改下 JS、CSS 的請求 URL 便可,好比加一個查詢參數。效果以下:

Expires

Expires 也是用來控制緩存,與 Cache-Control 不同的是,Expires 響應頭包含日期/時間, 即在此時候以後,響應過時。無效的日期,好比 0, 表明着過去的日期,即該資源已通過期。用法以下:

//語法
  Expires: <http-date> //實例 response.setHeader('Expires', 'Wen, 31 Jul 2018 15:55:10 GMT'); 複製代碼

在有效期以內,重複的請求也會被瀏覽器阻止,轉而從內存中讀取文件。

一樣的更改請求的 URL 便可在有效期內更新文件。

須要注意的是,Expires 返回的是服務器時間,而瀏覽器在進行時間判斷時是以本地時間爲基準的,若是本地時間與服務器時間相差過大,請求或許會出現 bug。好比將本地時間調整至有效期以後,那麼每次請求都發送給服務器,不會被瀏覽器阻止。

而且當 Expires 與 Cache-Control 同時設置時,Expires 會被忽略,只有 Cache-Control 起做用。

ETag

ETag HTTP 響應頭是資源的特定版本的標識符。這可讓緩存更高效,並節省帶寬,由於若是內容沒有改變,Web 服務器不須要發送完整的響應。而若是內容發生了變化,使用 ETag 有助於防止資源的同時更新相互覆蓋(「空中碰撞」)。

上面是 MDN 對 ETag 的介紹,通俗的來說,就是 ETag 記錄了請求的文件的版本號,瀏覽器在每次請求這個文件的時候,會帶上這個版本號(做爲 If-None-Match 字段的值),服務器若是發現文件版本號沒有發生變化,也就是文件沒有發生改變,那就不須要從新將文件發送給瀏覽器,讓瀏覽器在緩存中讀取以前下載的文件便可。

能夠利用 MD5 值做爲文件的版本號,由於即便一個文件只發送了細微的變化,它的 MD5 值也會發生很大的變化。

ETag 的用法以下:

//語法
  ETag: "<etag_value>"

  //實例
  response.setHeader('ETag', fileMd5)
複製代碼

結果以下圖所示:

能夠看到,雖然是利用了緩存,但與前面的兩種方法相比,處理時間並不是爲 0ms。這是由於它確實向服務器發出了請求,只是服務器在比較 ETag 值以後,沒有將文件發送給瀏覽器而已。

Last-Modified

Last-Modified 是一個響應首部,其中包含源頭服務器認定的資源作出修改的日期及時間。

與 ETag 相似,也是設定一個特徵值,服務器經過比較特徵值來判斷是否讓瀏覽器運用緩存,只不過 ETag 用的是文件的版本號,Last-Modified 用的是文件最後的修改時間。用法以下:

//語法
  Last-Modified: <day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT

  //實例
  let lastModified = fs.statSync('./css/style.css', 'utf8').mtime.toGMTString();
  response.setHeader('Last-Modified', lastModified);
複製代碼

只要文件沒有改變,也就是文件修改時間沒有發生變化,那麼服務器便不會向瀏覽器發送這個文件,而是讓瀏覽器去讀取緩存。

與 ETag 相似的是,它也會發出請求,只是服務器不返回文件而已。

相關文章
相關標籤/搜索