淺談 Cookie-Session 、Jwt 兩種身份認證機制

HTTP 是無狀態的協議

咱們都知道 HTTP 是無狀態(stateless)的協議:HTTP 對於事務處理沒有記憶能力,不對請求和響應之間的通訊狀態進行保存。 使用 HTTP 協議,每當有新的請求發送時,就會有對應的新響應產生。協議自己並不保留以前一切的請求或響應報文的信息。這是爲了更快地處理大量事務,確保協議的可伸縮性,而特地把 HTTP 協議設計成如此簡單的。html

但是,隨着 Web 的發展,早期這種無狀態的特性卻帶來了不少不方便性,好比說用戶登陸新浪微博,在登陸頁輸入用戶名、密碼以後進入首頁,可是因爲 HTTP 是無狀態的,HTTP 並不知道上一次的 HTTP 請求是否經過了驗證,更沒法得知當前用戶的具體信息。前端

最簡單的解決方案就是在全部的請求裏面都帶上用戶名和密碼,這樣雖然可行,可是大大加劇了服務器的負擔(對於每一個 request 都須要到數據庫驗證),並且用戶也要每進入一個頁面輸入一次密碼,毫無用戶體驗可言。web

爲此,引入了各類身份認證機制,這裏說一下 Cookie-Session 和 Jwt 機制。算法

Cookie-Session 機制

什麼是 Cookie?

Cookie 是由 HTTP 服務器設置的,保存在瀏覽器中的小型文本文件,其內容爲一系列的鍵值對。在 Chrome 中,經過開發者工具 -> Application -> Cookies 可查看 數據庫

保存在瀏覽器中的 Cookie
這裏簡單介紹一下一些字段意思:

Expires:Cookie 的過時時間,默認過時時間爲用戶關閉瀏覽器時。json

HttpOnly:指示瀏覽器不要在除了 HTTP(或者 HTTPS)請求以外暴露 Cookie。經過 JavaScript 腳本沒法訪問到 Cookie,能有效防止 XSS 攻擊後端

Secure:設置 Cookie 的 Secure 屬性爲 true 時,意味着 Cookie 通訊只限於加密傳輸,指示瀏覽器僅僅在經過安全/加密鏈接才能使用 Cookie。也就是說 Cookie 只有在 HTTPS 協議下才能上傳到服務器,而 HTTP 協議下是沒法上傳的。跨域

Cookie 傳遞過程

  1. 瀏覽器向某個 URL 發送請求
  2. 對應的服務器收到該 HTTP 請求,生成要發給瀏覽器的 HTTP 響應
  3. 在響應頭中加入 Set-Cookie 字段,值爲要設置的的Cookie
  4. 瀏覽器收到來自服務器的 HTTP 響應
  5. 瀏覽器在響應頭中發現了 Set-Cookie 字段,就會將該字段的值保存在內存或者是硬盤中。
  6. 當下一次向該服務器發送 HTTP 請求時,會將服務器設置的 Cookie 附加在 HTTP 請求的字段 Cookie 中。
  7. 服務器收到這個 HTTP 請求以後,發現請求頭中有 Cookie 字段,就知道了已經處理過這個用戶的請求了。
  8. 過時的 Cookie 會被刪除

Cookie 傳遞過程

什麼是 Session?

相對於保存在瀏覽器中的 Cookie,Session 是存儲在服務器端的,避免了在客戶端中儲存敏感數據。而且存取方式不一樣,Cookie 只能保存 ASCII 字符串,例如須要存取 Unicode 字符或者二進制數據,須要先進行編碼。而Session中可以存取任何類型的數據。Session 通常配合 Cookie 使用,也就是接下來要說到的 Cookie-Session 機制。瀏覽器

基於 Cookie-Session 身份驗證機制的過程

  1. 用戶輸入登陸信息
  2. 服務端驗證登陸信息是否正確,若是正確就在服務器端爲這個用戶建立一個 Session,並把 Session 存入數據庫
  3. 服務器端會向客戶端返回帶有 sessionID 的 Cookie
  4. 客戶端接收到服務器端發來的請求以後,看見響應頭中的 Set-Cookie 字段,將 Cookie 保存起來
  5. 接下來的請求中都會帶上這個 Cookie,服務器將 sessionID 和 數據庫中的相匹配,若是有效則處理該請求
  6. 若是用戶登出,Session 會在客戶端和服務器端都被銷燬

Session-Cookie 機制的缺陷

  1. 擴展性很差,當擁有多臺服務器的狀況下,如何共享 Session 會成爲一個問題,也就是說,用戶第一個訪問的時候是服務器 A,而第二個請求被轉發給了服務器 B,那服務器 B 沒法得知其狀態。(舉例來講,A 網站和 B 網站是同一家公司的關聯服務。用戶只要在其中一個網站登陸,再訪問另外一個網站自動登陸)
  2. 安全性很差,攻擊者能夠利用本地 Cookie 進行欺騙和 CSRF 攻擊。
  3. Session 保存在服務器端,若是短期內有大量用戶,會影響服務器性能。
  4. 跨域問題,Cookie 屬於同源策略限制的內容之一。

Jwt 機制

JWT(JSON Web Token) 是由 RFC7519 定義的,是一個在雙方之間安全的傳達一組信息的 JSON 對象。安全

JWT 組成

JWT 由三個部分組成:header、payload、signature 每一個部分中間使用 . 來分隔,其中,header 和 payload 使用 Base64URL 進行編碼:

base64UrlEncode(header).base64UrlEncode(payload).signature
複製代碼

header

header 部分是一個 JSON 對象,用來描述 JWT 的元數據:

{
  "typ": "JWT",   //  表示對象是一個 JWT
  "alg": "HS256"  //  表示使用哪一種 Hash 算法來建立簽名,這裏是 HMAC-SHA256
}
複製代碼

payload

payload 部分也是一個 JSON 對象,實際須要傳遞的數據被存放在這裏。咱們除了使用官方提供的七個字段以外,也可使用自定義的私有字段。

{
  "sub": "title",
  "name": "Yeoman"
}
複製代碼

JWT 默認是不加密的,任何人均可以讀到,因此不要把祕密信息放在這個部分。

signature

signature 是對前兩個部分的簽名,防止數據被篡改。

data = base64urlEncode( header ) + "." + base64urlEncode( payload );
signature = Hash( data, secret );
複製代碼

使用 Base64URL 編碼的 header 和 payload 中間用 . 隔開,再使用 header 中指定的 Hash 算法,加上密鑰對這個字符串進行 Hash 獲得 signature

工做流程

  1. 前端將本身的用戶名和密碼發送到後端的接口
  2. 後端覈對用戶名和密碼以後,將用戶的一些信息做爲 payload,生成 JWT
  3. 後端將 JWT 做爲登陸成功的返回結果返回給前端。前端能夠將其結果保存在 localStorage/sessionStorage 中,登出時刪除 JWT 便可。(最好不要保存在 Cookie 中,用了 Cookie 就不能設置 HTTPonly,而且存在跨域問題)
  4. 每一次請求都將 JWT 放在 HTTP 請求頭中的 Authorization 位,這樣相比放在 Cookie 中能夠跨域。
Authorization: Bearer <token>
複製代碼
  1. 服務器解碼 JWT,若是 token 有效,那麼處理這個請求
  2. 用戶登出,在客戶端刪除 token 便可,與服務端無關

JWT 特色

  1. JWT 默認是不加密的
  2. JWT 的目的是用來驗證來源可靠性,並非保護數據和防止未經受權的訪問。(能夠類比成一張電影票,只能驗證電影票是不是真的,電影票也有一些基本信息,可是他人也可使用你的電影票,若是可能的話)一旦暴露,任何人均可以得到權限。爲了減小盜用,JWT 的有效期應該設置得比較短,對於一些比較重要的權限,使用時應該再次對用戶進行認證。
  3. 最大的缺點是 token 過時處理問題,因爲服務器不保存 Session 狀態,所以沒法在使用過程當中廢止或者更改權限。也就是說,一旦 JWT 簽發了,在到期以前就會始終有效,除非服務器部署額外的邏輯。

複習

這裏再次複習一下相關知識:

同源策略限制的內容

  1. Cookie、LocalStorage、SessionStorage、IndexedDB 等存儲性內容
  2. DOM 節點
  3. Ajax 發送請求後,結果被瀏覽器攔截

Cookie 和 Session 的區別

  1. 存取方式不一樣:Cookie 只能保存 ASCII 字符串,例如須要存取 Unicode 字符或者二進制數據,須要先進行編碼。而Session中可以存取任何類型的數據
  2. 隱私策略不一樣:Cookie 存儲在瀏覽器中,Session 存儲在服務器上。
  3. 服務器壓力不一樣:Session 是保管在服務器上的,每一個用戶都會產生一個 Session 。假如併發訪問的用戶十分多,會產生大量的 Session ,耗費大量的內存。

援引

JSON Web Token 入門教程

淺談session,cookie和jwt(Json Web Token)認證方式

cookie-session機制與JWT機制對比

五個步驟輕鬆弄懂 JSON Web Token(JWT)

相關文章
相關標籤/搜索