hamburger-icon hamburger-icon

你是誰?淺談身分認證方式

kai98k

這個作者很懶,什麼都沒留下...

身分驗證與資安問題一直是目前仍然很火紅的問題,由於 Http 本身是屬於無狀態,所以說每次的 Request/Response 都是獨立的,所以就需要 session、cookie 和 token 來做狀態/資訊管理(stateful),且可能還會有許多不同的應用,像是使用 Redis 等等。

Basic 驗證

Basic 驗證的工作原理是,當客戶端(如瀏覽器或應用程式)向伺服器發送請求時,會在 HTTP 首部中包含一個 Authorization 欄位,其中包含用戶名和密碼的 Base64 編碼。伺服器接收到請求後,會解碼 Authorization 欄位中的用戶名和密碼,並驗證其是否有效。如果用戶名和密碼有效,則伺服器將返回請求的數據,否則將返回一個錯誤 Response。

GET /secure-data HTTP/1.1
Host: example.com
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

在這個例子中,用戶名是 “username”,密碼是 “password”,並且被 Base64 編碼後作為 Authorization 欄位的值。伺服器會解碼這個值,並使用明文的用戶名和密碼進行驗證。

儘管 Basic 驗證非常簡單易於實現,但它有一些限制。最明顯的限制是,它以明文的方式傳輸用戶名和密碼,這使得它容易受到攻擊者的竊聽和嗅探。另外,Basic 驗證也沒有提供身份驗證後繼續授權的機制,因此不適用於需要更高安全性要求的應用程式和 API。因此,現在一般不建議使用 Basic 驗證,而推薦使用更安全的驗證方式。

Session-based 認證

就像在早餐店點餐時,客人口頭跟老闆點餐,老闆會將餐點及客人資料 key 進電腦裡,老闆會印出號碼單給客人,當客人要取餐時,要再將號碼單給老闆。客人這邊要負責保管號碼單,而老闆這邊需要負責管理各個客人的資料,並依據號碼單給客人相對應的東西。

當用戶在客戶端(前端)登入時,會將帳號密碼 Post 到伺服器端,此時,在伺服器端的後端程式會利用用戶資訊創建一個 Session,並返回給客戶端 Session ID,而在之後的 Request 中都在 Http Cookie 帶上這個 Session ID,一旦伺服器在收到 Request 時,發現有 Session ID 時,就能尋找相對應的 Session ID,來取得存於該 Session 的用戶資料。

HTTP cookie(web cookie、browser cookie)為伺服器傳送予使用者瀏覽器的一個小片段資料。瀏覽器可能儲存並於下一次請求回傳 cookie 至相同的伺服器,它記住了無狀態(stateless)HTTP 協議的有狀態資訊

Cookies 主要用於三個目的:

  1. Session 管理
    帳號登入、購物車、遊戲分數,或任何其他伺服器應該記住的資訊

  2. 個人化
    使用者設定、佈景主題,以及其他設定

  3. 追蹤
    記錄並分析使用者行為

以上三點都不應該包含機敏資料,因為如此一來使用者也可以任意串改 Cookie 的值,來誘騙伺服器,能放的是相對應該資料的 ID。

Set-Cookie 是一個 HTTP 標頭,它用於在客戶端(例如瀏覽器)和伺服器之間傳遞一個包含有關用戶 Session 和其他狀態信息的小數據塊。它通常是在伺服器端將數據儲存在用戶瀏覽器的 Cookie 中,這樣伺服器就可以通過 Cookie 來識別用戶並維護 Session 狀態。

Set-Cookie 設置屬性
NAME=VALUE 賦予 Cookie 的名稱跟值
expires=DATE Cookie 的有效期,預設為瀏覽器關閉
path=PATH 伺服器上的文件目錄作為 Cookie 物件
domain=域名 Cookie 物件的域名
Secure 只在 HTTPS 時才發送
HttpOnly 使 Cookie 不能被 Javascript 訪問

Session 身分驗證缺點

  1. Session 劫持:如果攻擊者能夠取得有效的Session ID,他們就可以假冒用戶身份,訪問和修改用戶的資料。攻擊者可能會使用一些技巧,例如在公共 Wi-Fi 上使用偽造的網站來竊取Session ID。

  2. CSRF 攻擊:跨站請求偽造(CSRF)攻擊是一種利用受害者在瀏覽器上的活動身份驗證權限,從而在背後完成一些不被受害者期望的操作的攻擊。攻擊者可能會通過將偽造的請求傳送到瀏覽器中的漏洞網站,以利用用戶的身份在背後訪問其他受保護的網站。

  3. 無法輕易地從伺服器端中斷用戶的 Session:因為 Session ID 通常存儲在用戶端 Cookie 中,伺服器沒有辦法直接終止用戶的 Session。即使伺服器端檢測到 Session 劫持或 CSRF 攻擊,也無法直接中斷 Session,必須等待會話過期或重置用戶的 Session ID。

為了減少這些風險,需要採取額外的措施,例如使用 HttpOnly 和 Secure 標誌、限制 Session 持續時間、定期重置 Session ID 等。

Cookie 同源政策是瀏覽器的一種安全機制,用於限制網站之間在瀏覽器中共享 Cookie。根據同源政策,網站只能訪問與自己位於相同協議、主機和端口號的 Cookie。這樣可以避免一個網站存取或修改其他網站的 Cookie,從而保護用戶的隱私和安全。

例如,如果網站 A 嘗試存取網站 B 的 Cookie,則瀏覽器將拒絕該請求,因為它們的域名不同。同樣地,如果網站 A 嘗試將 Cookie 寫入網站 B 的 Cookie,則也會被拒絕,因為它們的域名不同。

Token-Based 認證

想像在早餐店點餐的時候,你用一串行話(大溫微奶肉蛋吐薯要胡不要茄)跟老闆點餐,這時候老闆用他超猛的大腦解析這串話需要出甚麼餐點,然後你要取餐的時候只要再講一次,老闆就會給你,你點的東西

剛開始碰到 Token 的概念時,總是想不明白為何要叫做”令牌”,直到理解其中的原理與 Basic 驗證不同的地方在於,不是單純將明碼變成 Base64 傳至伺服器,而是將機敏資訊過轉譯、加密成一組無意義的資訊,此時這組無意義的資訊就叫做 Token,而這個行為就叫做令牌化(Tokenization)

優點

  1. 在於它可以消除在伺服器上保存 Session 的需要。在傳統的基於 Session 的身份驗證中,伺服器需要在本地保存有關用戶的 Session,以便在用戶與伺服器之間交互時使用。但是,在 Token-based 認證中,所有必要的用戶資訊都儲存在 Token 中。

  2. 它使得跨多個伺服器或服務的身份驗證變得更容易。當用戶在不同的伺服器或服務之間進行交互時,每個服務都可以驗證該用戶的身份,而不需要共享 session 或在不同服務之間進行身份驗證。

JWT

在實現 Token-based 認證時,常見的方法是使用 JSON Web Token (JWT)。JWT 是一個開放的標準,定義了一種用於在不同方之間安全傳輸信息的格式。JWT 可以包含用戶的身份信息,以及其他相關資訊,例如過期時間和許可權等。用戶在通過身份驗證後,應用程式會將 JWT 返回給客戶端,客戶端之後每次請求都必須攜帶 JWT,以便在伺服器端進行身份驗證。

JWT 的結構包含三部分,分別是:

  1. Header:JWT 的標頭部分包含了關於該令牌的元數據,如令牌類型、加密算法等。

  2. Payload:JWT 的有效載荷部分包含了應用程序中的有關用戶身份和其他元數據的信息,如用戶 ID、角色、權限等。

  3. Signature:JWT 的簽名部分用於驗證令牌是否真實有效,確保在傳輸過程中沒有被修改或替換。

JWT 的運作流程通常包括以下幾個步驟:

  1. 用戶提交其憑證(如用戶名和密碼)到應用程序以進行身份驗證。
  2. 應用程序將驗證用戶的身份,並根據用戶的信息創建一個 JWT。
  3. 用戶在之後的請求中提交 JWT。
  4. 應用程序檢查 JWT 是否合法,並使用 JWT 中的信息驗證用戶的身份和授權。
  5. 如果 JWT 驗證成功,則用戶被授予訪問其所需資源的權限。

JWT 具有許多優點,例如可以跨多種平台使用,無需保存狀態,具有高度的可擴展性和自描述性等。此外,JWT 還可以與 OAuth 一起使用,以實現安全的身份驗證和授權,進一步保護用戶的隱私和資料安全。

OAuth

OAuth(Open Authorization)是一種開放標準的授權協議,用於授權用戶或應用程式訪問另一個用戶的資源,而不需要共享用戶的密碼。OAuth 協議通常用於網路應用程式和服務之間的安全授權,以便用戶可以安全地共享他們的資源和信息。

OAuth 協議使用了一個名為「授權令牌」(access token)的機制,以代表用戶的身份和權限。在 OAuth 的授權流程中,當用戶試圖訪問某個資源時,他們會被要求授權第三方應用程式訪問他們的資源。用戶可以通過登入到他們的帳戶,然後授予權限給該應用程式,以便該應用程式可以使用用戶的資源,而不需要知道用戶的密碼。

OAuth 協議主要包括以下幾個角色:

  • 用戶(resource owner):擁有需要被授權訪問的資源。
  • 第三方應用程式(client):需要訪問用戶的資源的應用程式。
  • 授權服務器(authorization server):負責驗證用戶的身份並授予令牌的服務器。
  • 資源服務器(resource server):實際存儲用戶資源的服務器。

OAuth 協議的工作流程大致如下:

  1. 第三方應用程式向授權服務器發出請求,請求授權訪問用戶的資源。
  2. 授權服務器驗證用戶的身份,並向用戶請求授權。
  3. 用戶授權第三方應用程式訪問他們的資源。
  4. 授權服務器向第三方應用程式發送一個授權令牌,代表著該應用程式被授權訪問用戶的資源。
  5. 第三方應用程式使用授權令牌訪問用戶的資源。

通過 OAuth 協議,用戶可以授權第三方應用程式訪問他們的資源,而不需要共享他們的密碼。這有助於保護用戶的機敏資訊的安全性。同時,OAuth 協議還可以幫助用戶控制哪些應用程式可以訪問他們的資源,從而增強了用戶對自己數據的控制權。

OAuth 協議有多個版本,包括 OAuth 1.0、OAuth 1.0a、OAuth 2.0 等。其中,OAuth 2.0 是最常用的版本,由於其簡單易用、靈活性高和可擴展性強,已成為許多網路應用程式和服務之間進行身份驗證和授權的標準協議。

總結

Session 認證通常是基於 cookie 和 session 的,當用戶登錄時,服務器會創建一個 session 對象,並將其唯一標識符(session ID)保存在用戶的 cookie 中。當用戶再次訪問站點時,瀏覽器會自動將 cookie 發送到服務器端,服務器端會檢查該 session ID 是否有效,並根據 session 中的信息判斷用戶是否已經登錄。

相對而言,JWT 認證是基於 JSON Web Token(JWT)的,JWT 是一種開放標準,它允許在網絡中安全地傳輸信息。在 JWT 認證中,當用戶登錄成功後,服務器會創建一個 JSON 對象,並使用密鑰將其加密為一個 Token。然後將該 Token 發送到客戶端,客戶端可以將其存儲在 cookie 中或者使用其他方式保存。當用戶再次訪問站點時,客戶端會將該 Token 發送到服務器端,服務器端使用密鑰對其進行驗證,以確定用戶的身份和權限。

總體來說,Session 認證通常需要在服務器端維護 session 物件,需要消耗服務器的資源,並且無法很好地支持跨域認證。而 JWT 認證則可以在客戶端維護,可以支持跨域認證,並且具有良好的可擴展性和安全性。

Reference

https://squareball.co/blog/the-difference-between-basic-auth-and-oauth