PHP怎樣處理JWT身份驗證 JWT令牌驗證的5個步驟解析

jwt驗證在php中需先接收并解析令牌,驗證簽名和聲明,最后進行授權。具體步驟為:1.接收jwt并存儲于header或Cookie;2.解析jwt獲取header、payload、signature;3.用密鑰重新計算簽名并比對;4.驗證payload中的聲明如exp、iss等;5.通過驗證后根據用戶信息授權。為防篡改應加強密鑰管理、使用https、選擇安全算法、定期換密鑰并對敏感數據加密。過期處理可采用刷新令牌、重新登錄、靜默刷新等方式。php常用庫如firebase/php-jwt和lcobucci/jwt簡化實現過程。jwt還可存入cookies、localstorage等但需注意安全風險。選庫時要考慮安全性、功能、性能、易用性和社區支持。

PHP怎樣處理JWT身份驗證 JWT令牌驗證的5個步驟解析

JWT(json Web Token)在PHP中的處理,核心在于驗證其真實性和有效性,確保只有授權用戶才能訪問受保護的資源。簡單來說,就是解析令牌,驗證簽名,檢查過期時間,然后根據令牌中的信息進行授權。

PHP怎樣處理JWT身份驗證 JWT令牌驗證的5個步驟解析

JWT身份驗證的5個步驟:

PHP怎樣處理JWT身份驗證 JWT令牌驗證的5個步驟解析

  1. 接收JWT: 客戶端在登錄后,服務器會生成一個JWT并返回給客戶端。客戶端需要將此JWT存儲起來,通常放在HTTP Header的Authorization字段中(例如:Authorization: Bearer ),或者存儲在Cookie中。后續客戶端每次請求受保護的資源時,都需要帶上這個JWT。

    立即學習PHP免費學習筆記(深入)”;

  2. 解析JWT: 在服務器端,首先要從請求頭或Cookie中獲取JWT。獲取到JWT后,需要對其進行解析。JWT本質上是一個字符串,由三部分組成,分別是Header(頭部)、Payload(負載)和Signature(簽名),這三部分用.連接。PHP可以使用explode()函數分割JWT字符串,分別獲取這三部分。

    PHP怎樣處理JWT身份驗證 JWT令牌驗證的5個步驟解析

  3. 驗證簽名: 這是JWT驗證的核心步驟。Header中包含了簽名算法,Payload包含了聲明(claims),而Signature則是通過Header指定的算法,使用密鑰對Header和Payload進行加密生成的。驗證簽名,需要使用相同的密鑰和算法,重新計算簽名,然后與JWT中的Signature進行比較。如果兩者一致,則說明JWT沒有被篡改。

  4. 驗證聲明(Claims): Payload中包含了一系列的聲明(Claims),這些聲明可以包含用戶的信息,也可以包含一些標準的聲明,例如exp(過期時間)、iat(簽發時間)、nbf(生效時間)、iss(簽發者)和aud(受眾)。服務器需要驗證這些聲明是否有效。例如,需要驗證exp聲明,判斷JWT是否已經過期。如果JWT已經過期,則驗證失敗。

  5. 授權: 如果JWT驗證通過,則可以從Payload中獲取用戶的信息,然后進行授權。例如,可以根據用戶ID從數據庫中查詢用戶的角色,然后判斷用戶是否具有訪問該資源的權限。

如何防止JWT被篡改?

JWT的核心安全機制在于簽名驗證。但僅僅依賴簽名是不夠的。

  • 密鑰管理: 密鑰的安全性至關重要。絕對不能將密鑰硬編碼在代碼中,或者存儲在版本控制系統中。最佳實踐是將密鑰存儲在安全的環境變量中,或者使用專門的密鑰管理服務。
  • 使用https 傳輸JWT時,務必使用HTTPS協議,防止中間人攻擊,竊取JWT。
  • 算法選擇: 應該選擇安全的簽名算法,例如HS256、RS256等。不建議使用弱算法,例如none算法,因為這種算法不需要簽名,任何人都可以偽造JWT。
  • 定期更換密鑰: 為了防止密鑰泄露后被長期利用,應該定期更換密鑰。更換密鑰后,需要通知所有使用該密鑰的服務,并確保舊的JWT仍然可以驗證,直到過期。
  • Payload加密: 雖然JWT本身不提供加密功能,但可以在Payload中對敏感信息進行加密,然后再生成JWT。這樣即使JWT被竊取,也無法直接獲取敏感信息。

JWT過期后如何處理?

JWT過期是身份驗證過程中常見的情況,處理方式直接影響用戶體驗。

  • 刷新令牌(Refresh Token): 這是最常見的解決方案。當JWT過期時,客戶端可以使用Refresh Token向服務器申請新的JWT。Refresh Token的有效期通常比JWT長,但也要進行安全保護,例如限制Refresh Token的使用次數,或者定期更換Refresh Token。
  • 重新登錄: 如果沒有Refresh Token,或者Refresh Token也過期了,那么客戶端需要重新登錄。這通常會導致用戶體驗下降,因為用戶需要重新輸入用戶名和密碼。
  • 靜默刷新: 可以在JWT過期前,提前發送請求,靜默刷新JWT。這樣可以避免用戶感知到JWT過期,提高用戶體驗。
  • 前端提示: 在前端,可以通過監聽JWT的過期時間,提前提示用戶JWT即將過期,并引導用戶進行刷新操作。

如何在PHP中實現JWT驗證?

PHP有很多JWT庫可以使用,例如firebase/php-jwt、lcobucci/jwt等。這些庫封裝了JWT的生成、解析和驗證過程,可以大大簡化開發工作。

以firebase/php-jwt為例,以下是一個簡單的JWT驗證示例:

<?php  require_once 'vendor/autoload.php';  use FirebaseJWTJWT; use FirebaseJWTKey;  $jwt = $_SERVER['HTTP_AUTHORIZATION']; // 從請求頭獲取JWT $key = 'your-secret-key'; // 你的密鑰  try {     $decoded = JWT::decode($jwt, new Key($key, 'HS256'));      // JWT驗證通過     print_r($decoded);  } catch (Exception $e) {     // JWT驗證失敗     echo 'JWT驗證失敗:' . $e->getMessage(); }

這個例子展示了如何使用firebase/php-jwt庫驗證JWT。首先,從請求頭中獲取JWT。然后,使用密鑰和算法,調用JWT::decode()函數驗證JWT。如果JWT驗證通過,則可以獲取JWT中的Payload。如果JWT驗證失敗,則會拋出一個異常。

實際項目中,需要根據業務需求,對JWT進行更復雜的驗證和處理。例如,可以驗證iss、aud等聲明,或者根據JWT中的用戶信息進行授權。

除了Authorization Header,JWT還能放在哪里?

雖然Authorization Header是最常見的選擇,但JWT的存儲位置并非一成不變。

  • Cookies: 將JWT存儲在HTTP Cookies中也是一種常見做法。 這在單頁應用(SPA)中尤其有用,因為瀏覽器會自動將Cookies發送到服務器。 但是,使用Cookies需要注意csrf(跨站請求偽造)攻擊,可以采用SameSite屬性來增加安全性。
  • LocalStorage/sessionstorage:瀏覽器端,還可以將JWT存儲在LocalStorage或SessionStorage中。 但這種方式存在xss(跨站腳本攻擊)的風險,惡意腳本可以訪問LocalStorage或SessionStorage中的JWT。 因此,需要對輸入和輸出進行嚴格的過濾,防止XSS攻擊。
  • 查詢參數(不推薦): 將JWT放在URL的查詢參數中是非常不安全的,因為URL會被記錄在服務器日志中,或者被分享給他人。 強烈不建議使用這種方式。

選擇哪種存儲方式,需要根據具體的應用場景和安全需求進行權衡。 Authorization Header通常被認為是相對安全的選擇,但結合Refresh Token機制,Cookie配合SameSite屬性也是可行的方案。

如何選擇合適的JWT庫?

選擇合適的JWT庫,關系到項目的開發效率和安全性。

  • 安全性: 首先要考慮的是JWT庫的安全性。 選擇那些經過安全審計,并且有良好社區支持的庫。 避免使用那些已經停止維護,或者存在已知安全漏洞的庫。
  • 功能: 不同的JWT庫提供的功能有所不同。 有些庫只提供基本的JWT生成、解析和驗證功能,而有些庫則提供更高級的功能,例如密鑰管理、聲明驗證、刷新令牌等。 選擇那些能夠滿足項目需求的庫。
  • 性能: JWT的生成和驗證過程會消耗一定的性能。 選擇那些性能優良的庫,可以提高應用的響應速度。 可以對不同的JWT庫進行性能測試,選擇性能最佳的庫。
  • 易用性: 選擇那些易于使用,并且有完善文檔的庫,可以降低開發成本,提高開發效率。
  • 社區支持: 選擇那些有活躍社區支持的庫,可以更容易地獲取幫助,解決問題。

在PHP中,firebase/php-jwt和lcobucci/jwt是兩個比較流行的JWT庫。firebase/php-jwt使用簡單,適合小型項目。lcobucci/jwt功能更強大,適合大型項目。

? 版權聲明
THE END
喜歡就支持一下吧
點贊15 分享