iT邦幫忙

2024 iThome 鐵人賽

DAY 19
0
Software Development

Django 2024: 從入門到SaaS實戰系列 第 21

Django REST framework: JWT與TokenAuthentication的全面比較

  • 分享至 

  • xImage
  •  

我們在昨天介紹了Django REST framework(DRF)中BasicAuthentication與TokenAuthentication的認證流程,並且也在認識認證流程的同時意識到這兩種方法各自的風險,並且也提到JSON Web Token(JWT)在某方面處理了這兩種方法各自的痛點

網路上關於介紹JWT的相關資訊非常多且十分詳細,尤其推薦:

是誰在敲打我窗?什麼是 JWT ?

JSON Web Token (JWT) explained

我們今天把重點放在JWT本身的特色、使用場景以及在納入資安考慮後應該要做什麼調整

在下一篇才會進行實際操作

今日重點:

  • 什麼是JWT
  • JWT的工作流程
  • JWT vs Token Authentication

什麼是JWT

JWT是一種基於JSON的開放標準(RFC 7519),用於在各方之間使用JSON物件的形式安全的傳遞資料,並且因為有經過數位簽章,因此可以被信任。

JWT的結構可以分成以下三點,每一部分以(.)點作為區分

  • Header
    • 通常包含兩部分:令牌的類型(JWT)和使用的哈希算法(如 HMAC SHA256 或 RSA)
    • 例如:{"alg": "HS256", "typ": "JWT"}
  • Payload
    • 包含關於實體(通常是用戶)和其他數據的聲明,避免在這裡放入敏感資訊。目的為存放實際要傳輸的資料
    • 例如:{"sub": "1234567890", "name": "John Doe", "iat": 1516239022}
  • Signature
    • 用於驗證消息在傳輸過程中沒有被更改,並且對於使用私鑰簽名的令牌,它還可以驗證 JWT 的發送方是否為它所稱的發送方,主要就是驗證token的有效性
<header>.<payload>.<signature>

並且JWT也有以下特點:

  • compact:代表資訊量較少,可以通過url參數、POST參數或是header內來傳遞
  • self-contained:像是payload中可以包涵一些訊息,如用戶名等等,不需要再重新找資料

JWT的工作流程

初始登入流程:

  • 用戶提供憑證(用戶名等等)
  • 服務端驗證憑證,生成兩個Token
    • Access Token:短期有效
    • Refresh Token:長期有效,如果Access Token過期可以用Refresh Token獲取
  • 服務端返回這兩個Token給客戶端
  • 客戶端存儲Token

正常請求流程:

  • 後續請求中,客戶端在 Authorization header 中發送 Access Token
  • 服務端驗證Access Token的簽名和有效期,無需查詢數據庫

Token刷新流程:

當 Access Token 過期時:

  • 客戶端使用 Refresh Token 請求新的 Access Token
  • 服務端驗證 Refresh Token
  • 如果有效,服務端生成新的 Access Token(有時也會更新 Refresh Token)
  • 服務端將新的 Access Token(和可能的新 Refresh Token)返回給客戶端
  • 客戶端使用新的 Access Token 重新發送原始請求

JWT vs Token Authentication

跟Token認證中有一些區別:

  • 儲存位置
    • Token:認證是存在資料庫中
    • JWT:存放在客戶端
  • 驗證過程
    • Token:每次請求都需要查詢資料庫
    • JWT:通過驗證簽名來驗證,無需從資料庫查詢
  • 性能
    • Token:需要資料庫查詢,用戶一多可能影響性能
    • JWT:驗證過程更快,不需要資料庫交互
  • 信息載荷
    • Token:通常只是一個隨機字符串,不包含額外訊息
    • JWT:可以在 payload 中包含額外的聲明(claims)

那我們可以從各方面比較一下兩者的優劣勢

安全特性 JWT 傳統 Token 優勢
信息包含 包含用戶信息,可能有信息洩露風險 通常只是隨機字符串,不包含敏感信息 傳統 Token*
密鑰管理 依賴於單一密鑰的安全性,一旦洩漏便可能有所有JWT都會被偽造 每個 Token 獨立,單個泄露影響有限 傳統 Token
撤銷機制 雖然有配置過期時間,但是配置過長的時間風險會提高 可以通過刪除數據庫記錄立即撤銷 傳統 Token*
跨域安全 適合跨域場景,不依賴 Cookie 如使用 Cookie 存儲,可能面臨 CSRF 風險 JWT
加密選項 可使用 JWE 進行加密 通常不提供內置加密 JWT
簽名驗證 使用密碼學簽名,可驗證完整性 通常依賴隨機性和數據庫查找 JWT
存儲位置 通常存儲在 localStorage,可能面臨XSS風險,可以使用 可存儲在 HttpOnly Cookie,對 XSS 有更好防護 傳統 Token*
性能與可擴展性 無需數據庫查詢,減少安全風險 需要資料庫查詢,可能增加攻擊面 JWT

但是這樣整理只是非常片面的資訊,使用工具時可以更靈活,我針對有打星號的部分再展開說明

  1. JWT的訊息中可以不要放敏感資訊,並且搭配HTTPS做使用
  2. 通常我們使用JWT時,不是為了要保持會話狀態,因此我們可以將Access Token設置較短的過期時間來避免風險,並且頻繁刪除資料庫的資料可能增加其壓力,不一定真的有優勢
  3. 我們可以將Access Token存在localStorage,然後Refresh Token放在cookie中,就能夠過HttpOnly Cookie等方式做到更全面的資安防護。但是也不是HttpOnly Cookie就是萬能的,雖然能抵擋XXS抵擋惡意JS腳本取的Cookie,但是還是有方法繞過取得Cookie

選擇哪種方法主要取決於具體需求和應用場景。例如:

  • 臨時憑證、第三方應用授權等短時間的訊息交互,那麽JWT是很好的選擇
  • 如果構建分布式系統或微服務架構,JWT 可能更有優勢
  • 如果跨域安全是一個主要考慮因素,JWT 可能是更好的選擇

今日總結

我們今天介紹了另一種認證的方式:JWT,並且詳細的比較了JWT與DRF內建Token認證的比較
以及也考慮到實作上如果納入資安的考量,我們可以在對JWT的認證系統能有什麼改良
我們下一篇就來實際進行應用吧!


上一篇
Django REST framework: 基礎認證防線 - BasicAuthentication與 TokenAuthentication
下一篇
Django REST framework: 掌握 JWT、CORS 和 Cookie 處理技巧
系列文
Django 2024: 從入門到SaaS實戰31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言