php處理jwt令牌的核心在于驗證和生成,確保api安全可靠。1. 引入jwt庫:通過composer安裝firebase/php-jwt;2. 生成jwt:構建包含用戶信息的payload并使用密鑰簽名;3. 傳遞jwt:將生成的令牌返回客戶端并通過authorization頭部發送;4. 驗證jwt:從請求頭中獲取并使用密鑰驗證令牌,捕獲異常處理錯誤;5. 設置合適的過期時間:根據應用場景選擇短、中或長過期時間;6. 處理jwt刷新:頒發refresh Token并與數據庫關聯,實現無感刷新;7. 防止jwt被篡改:使用強密鑰、定期更換、保護存儲及使用https傳輸。
PHP處理JWT令牌的核心在于驗證和生成,確保你的API安全可靠。簡單來說,就是用一個密鑰對用戶身份信息進行簽名,然后客戶端帶著這個簽名來訪問你的API,你再用同樣的密鑰驗證這個簽名,確認身份。
解決方案
PHP處理JWT令牌主要分為以下幾個步驟:
-
引入JWT庫: 首先,你需要一個JWT庫來簡化操作。比較流行的選擇是firebase/php-jwt。你可以通過composer安裝:
立即學習“PHP免費學習筆記(深入)”;
composer require firebase/php-jwt
-
生成JWT: 當用戶登錄成功后,你需要生成一個JWT。這通常涉及到以下步驟:
-
構建payload: Payload包含你想在令牌中存儲的用戶信息,例如用戶ID、用戶名、權限等。Payload必須是json格式。
$payload = array( "iss" => "your-domain.com", // 簽發者 "aud" => "your-domain.com", // 接收者 "iat" => time(), // 簽發時間 "nbf" => time(), // 生效時間 "exp" => time() + 3600, // 過期時間(1小時) "user_id" => $user_id, // 用戶ID "username" => $username // 用戶名 );
-
設置密鑰: 密鑰用于簽名JWT。務必使用一個強壯的、只有服務器知道的密鑰。
$key = "YourSecretKey"; // 請替換成你的強密鑰
-
生成JWT: 使用JWT庫生成令牌。
use FirebaseJWTJWT; $jwt = JWT::encode($payload, $key, 'HS256');
-
-
傳遞JWT: 將生成的JWT返回給客戶端。客戶端通常會將JWT存儲在localStorage、sessionstorage或Cookie中,并在后續的請求中通過Authorization頭部(Bearer Token)發送給服務器。
-
驗證JWT: 在API端點,你需要驗證JWT。
-
從請求頭中獲取JWT:
$authHeader = $_SERVER['HTTP_AUTHORIZATION']; $jwt = str_replace('Bearer ', '', $authHeader); // 移除 "Bearer " 前綴
-
驗證JWT: 使用JWT庫驗證令牌。
use FirebaseJWTJWT; use FirebaseJWTKey; use FirebaseJWTExpiredException; use FirebaseJWTSignatureInvalidException; use FirebaseJWTBeforeValidException; try { $decoded = JWT::decode($jwt, new Key($key, 'HS256')); // JWT驗證成功,可以訪問 $decoded 獲取payload中的信息 $user_id = $decoded->user_id; $username = $decoded->username; } catch (ExpiredException $e) { // 令牌已過期 http_response_code(401); echo json_encode(array("message" => "Token expired.")); } catch (SignatureInvalidException $e) { // 簽名無效 http_response_code(401); echo json_encode(array("message" => "Invalid signature.")); } catch (BeforeValidException $e) { // 令牌尚未生效 http_response_code(401); echo json_encode(array("message" => "Token not yet valid.")); } catch (Exception $e) { // 其他錯誤 http_response_code(401); echo json_encode(array("message" => "Invalid token.")); }
-
如何選擇合適的JWT過期時間?
過期時間的選擇取決于你的應用場景。
- 短過期時間 (例如 15 分鐘 – 1 小時): 適合安全性要求高的應用,例如銀行應用。即使令牌泄露,風險也很小。但用戶需要頻繁刷新令牌。
- 中等過期時間 (例如 1 天 – 1 周): 適合大部分應用,在安全性和用戶體驗之間取得平衡。
- 長過期時間 (例如 1 個月 – 1 年): 不推薦。如果令牌泄露,風險很大。只適合對安全性要求極低的應用,例如只需要識別用戶身份的應用。
記住,永遠不要將敏感信息直接存儲在JWT的payload中。Payload可以被客戶端解碼,所以只能存儲非敏感信息,例如用戶ID。
如何處理JWT刷新?
JWT刷新是指在JWT過期之前,獲取一個新的JWT。這可以避免用戶頻繁登錄。常見的做法是使用refresh token。
- 頒發refresh token: 在用戶登錄成功后,除了頒發JWT之外,還頒發一個refresh token。Refresh token的過期時間通常比JWT長。
- 存儲refresh token: 將refresh token存儲在數據庫中,與用戶ID關聯。
- 刷新JWT: 當JWT過期后,客戶端使用refresh token向服務器請求新的JWT。服務器驗證refresh token的有效性,如果有效,則頒發新的JWT和refresh token。
需要注意的是,refresh token也需要保護。建議使用HTTPS協議,并對refresh token進行加密存儲。
如何防止JWT被篡改?
JWT的安全性依賴于密鑰的安全性。如果密鑰泄露,攻擊者可以偽造JWT。
- 使用強密鑰: 使用足夠長的隨機字符串作為密鑰。
- 定期更換密鑰: 定期更換密鑰可以降低密鑰泄露的風險。
- 保護密鑰: 不要將密鑰存儲在代碼中。可以使用環境變量或配置文件來存儲密鑰。
- 使用HTTPS: 使用HTTPS協議可以防止中間人攻擊,保護JWT在傳輸過程中不被竊取。
另外,還可以考慮使用雙重驗證(2FA)來提高安全性。即使JWT泄露,攻擊者也無法訪問用戶的賬戶。