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

小明一點也不酷發表於2019-08-16

HTTP 是無狀態的協議

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

可是,隨著 Web 的發展,早期這種無狀態的特性卻帶來了很多不方便性,比如說使用者登入新浪微博,在登入頁輸入使用者名稱、密碼之後進入首頁,但是由於 HTTP 是無狀態的,HTTP 並不知道上一次的 HTTP 請求是否通過了驗證,更無法得知當前使用者的具體資訊。

最簡單的解決方案就是在所有的請求裡面都帶上使用者名稱和密碼,這樣雖然可行,但是大大加重了伺服器的負擔(對於每個 request 都需要到資料庫驗證),而且使用者也要每進入一個頁面輸入一次密碼,毫無使用者體驗可言。

為此,引入了各種身份認證機制,這裡說一下 Cookie-Session 和 Jwt 機制。

Cookie-Session 機制

什麼是 Cookie?

Cookie 是由 HTTP 伺服器設定的,儲存在瀏覽器中的小型文字檔案,其內容為一系列的鍵值對。在 Chrome 中,通過開發者工具 -> Application -> Cookies 可檢視

儲存在瀏覽器中的 Cookie
這裡簡單介紹一下一些欄位意思:

Expires:Cookie 的過期時間,預設過期時間為使用者關閉瀏覽器時。

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)

相關文章