【SSO單點登入】JWT入門概述&&殘留的安全問題

語言: CN / TW / HK

theme: smartblue highlight: solarized-light


持續創作,加速成長!這是我參與「掘金日新計劃 · 10 月更文挑戰」的第 3 天,點選檢視活動詳情

大家好,我是melo,一名大三後臺練習生,不知不覺練習時間長達一年了!!!

👉本篇速覽

  • 前後端分離會話問題以及解決方案
  • JWT概述入門
  • JWT優勢
  • JWT殘留的問題
    • redis白名單&黑名單機制
    • HTTPS中的數字簽名機制

1、前後端分離會話問題

【1】問題追蹤

  1. 前面我們實現分散式的session會話快取,但是我們發現此功能的實現是基於瀏覽的cookie機制,也就是說使用者禁用cookie後,我們的系統會就會產生會話不同的問題
  2. 而且服務端還需要儲存session,佔據了很多記憶體空間

【2】解決方案

   我們的前端可能是web、Android、ios等應用,同時我們每一個介面都提供了無狀態的應答方式,這裡我們提供了基於JWT的token生成方案
  1. 使用者登陸之後 , 使用JWT根據使用者的特有資訊【比如userId】頒發簽名並設定過期時間(類似session過期時間相同),返回token給前端

  2. 前端將token儲存到客戶端本地,並且之後每次傳送請求時都在header上攜帶token

  3. 後臺設定攔截器,每次請求都驗證token是否有效

    那麼jwt到底是什麼呢?

🎈2、JWT概述

JWT(JSON WEB TOKEN):JSON網路令牌,JWT是一個輕便的安全跨平臺傳輸格式,定義了一個緊湊的自包含的方式在不同實體之間安全傳輸資訊(JSON格式)。它是在Web環境下兩個實體之間傳輸資料的一項標準。實際上傳輸的就是一個字串。

  • 廣義上:JWT是一個標準的名稱;
  • 狹義上:JWT指的就是用來傳遞的那個token字串

JWT由三部分構成:header(頭部)、payload(載荷)和signature(簽名)。

Header

儲存兩個變數

  • alg:簽名演算法(也就是下面將Header和payload加密成Signature)預設是 HMAC SHA256(寫成 HS256)
  • typ:令牌型別,也就是JWT json { "alg": "HS256", "typ": "JWT" }

    JSON 形式的 Header 被轉換成 Base64 編碼,成為 JWT 的第一部分。

payload

儲存很多東西,基礎資訊有如下幾個

  1. 簽發人,也就是這個“令牌”歸屬於哪個使用者。一般是userId
  2. 建立時間,也就是這個令牌是什麼時候建立的
  3. 失效時間,也就是這個令牌什麼時候失效(session的失效時間)
  4. 唯一標識,一般可以使用演算法生成一個唯一標識(jti==>sessionId)
  5. iss (issuer):簽發人
  6. exp (expiration time):過期時間
  7. sub (subject):主題
  8. aud (audience):受眾
  9. nbf (Not Before):生效時間
  10. iat (Issued At):簽發時間
  11. jti (JWT ID):編號

    Payload 部分預設是不加密的,一定不要將隱私資訊存放在 Payload 當中!!! JSON 形式的 Payload 被轉換成 Base64 編碼,成為 JWT 的第二部分。

JWT 的 Token 相當是明文,是可以解密的,任何存在 payload 的東西,都沒有祕密可言,所以隱私資料不能簽發 token。

Signature

這個是上面兩個【Header和payload】經過Header中的演算法加密生成的,用於比對資訊,防止篡改Header和payload

首先,需要指定一個金鑰(secret)。這個金鑰只有伺服器才知道,不能洩露給使用者。然後,使用 Header 裡面指定的簽名演算法(預設是 HMAC SHA256),按照下面的公式產生簽名。

HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

算出簽名以後,把 Header、Payload、Signature 三個部分拼成一個字串,每個部分之間用"點"(.)分隔,就可以返回給使用者。

然後將這三個部分的資訊經過加密生成一個JwtToken的字串,傳送給客戶端,客戶端儲存在本地。當客戶端發起請求的時候攜帶這個到服務端(可以是在cookie,可以是在header),在服務端進行驗證,我們需要解密對應的payload的內容

優勢

  • 適合於分散式,因為不需要儲存在服務端了
  • 而且token自帶了payload可以存放一些用來校驗的使用者資訊,相當於客戶端存放了,原本用session的話是我們服務端去存一下loginUser在session中,然後他們做敏感操作比如修改的時候,我們通常需要去驗證是不是本人,通過他傳的userId去跟session中的比較

    而現在我們去跟他客戶端發過來的token比就好了

殘留問題

  1. 退出登入的時候,一般都是前端刪掉儲存的token即可,但這樣會不會有安全問題呢?這意味著這個token其實還是可以用的,一旦洩露就很危險了,此時我們應該如何處理呢?要知道token一旦簽發後,是沒辦法主動過期的
  2. token放在header裡邊,開啟控制檯就能看到,那別人能否拿到我們的token,去篡改為其他的身份呢?或者說主動捏造一個token

這些問題,我們統一留到下篇來解決~

💠下篇預告

  • 本篇簡單入門了JWT,並留下了兩個安全問題,下篇我們將探探解決方案,涉及到redis白名單&黑名單機制,以及HTTPS中的數字簽名機制,敬請期待

🧿友鏈