使用firebase/php-jwt忽略JWT过期验证并获取Payload的方法
解决方案:忽略JWT过期验证并完成有效性校验
核心思路
firebase/php-jwt库的JWT::decode方法支持通过选项参数跳过过期时间校验,只需在调用时传入['ignore_expiration' => true]即可。同时仍需确保令牌的签名有效性、iss、uid等自定义字段的校验,避免安全风险。
修改后的完整代码
<?php use Firebase\JWT\JWT; use Firebase\JWT\Key; use Firebase\JWT\SignatureInvalidException; use Firebase\JWT\BeforeValidException; use Firebase\JWT\InvalidArgumentException; require_once ("autoload.php"); function checkJWT($con,$userID,$jwt) { $domainName = "firebase-XXXXX-XXXXX@XXXXX-XXXXX-XXXXX.iam.gserviceaccount.com"; $secret_Key = "-----BEGIN PRIVATE KEY-----\XXXXXXX--XXXXX---END PRIVATE KEY-----\n"; // 修复SQL注入风险:使用预处理语句 $sql = "SELECT JWT,created FROM sample where id = ?"; $stmt = mysqli_prepare($con, $sql); mysqli_stmt_bind_param($stmt, "i", $userID); mysqli_stmt_execute($stmt); $res = mysqli_stmt_get_result($stmt); $data = mysqli_fetch_array($res); if($data['JWT'] == $jwt){ $res = openssl_get_privatekey($secret_Key); $details = openssl_pkey_get_details($res); $publicKey = $details['key']; $token = null; try{ // 传入ignore_expiration选项跳过过期校验 $token = JWT::decode( $jwt, new Key($publicKey, 'RS256'), ['ignore_expiration' => true] ); }catch ( \Firebase\JWT\ExpiredException $exception ){ // 过期异常已被忽略,无需额外处理 }catch(SignatureInvalidException $e){ // 签名无效,直接拒绝 return false; }catch(BeforeValidException $e){ // 令牌未到生效时间,拒绝 return false; }catch(InvalidArgumentException $e){ // 令牌格式错误,拒绝 return false; } // 校验令牌核心字段有效性 if (!$token || $token->iss !== $domainName || $token->uid !== $userID || $token->created !== $data['created']){ return false; }else{ return true; } } return false; } function generateJWT($con,$userID,$cretedTime) { $domainName = "firebase-XXXXX-XXXXX@XXXXX-XXXXX-XXXXX.iam.gserviceaccount.com"; $secret_Key = "-----BEGIN PRIVATE KEY-----\XXXXXXX--XXXXX---END PRIVATE KEY-----\n"; $date = time(); $request_data = [ 'iss' => $domainName, 'sub' => $domainName, 'aud' => "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit", 'iat' => $date, 'exp' => $date+(60*60), 'uid' => $userID, 'created' => $cretedTime, ]; $newToken = JWT::encode($request_data,$secret_Key,'RS256'); // 修复SQL注入风险:使用预处理语句 $sqlQuery = "UPDATE `sample` SET `JWT` = ? WHERE `id` = ?"; $stmt = mysqli_prepare($con, $sqlQuery); mysqli_stmt_bind_param($stmt, "si", $newToken, $userID); if(mysqli_stmt_execute($stmt)){ return $newToken; }else { return 'Unable To Process'; } } ?>
关键说明
ignore_expiration仅跳过exp字段的过期校验,令牌的签名有效性、iat生效时间等核心校验仍会执行,确保令牌未被篡改。- 必须保留
iss、uid、created等自定义字段的校验,避免非法令牌通过验证。 - 原代码存在SQL注入风险,已修改为预处理语句,这是生产环境的必要安全措施。
内容的提问来源于stack exchange,提问作者Ritu
相关产品推荐
相关产品推荐

