You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调试PHP验证Firebase JWT时遇算法密钥错误问题求助

问题分析与解决

核心问题

  1. 算法不匹配:你的JWT令牌头部显示使用的是RS256算法(从eyJhbGciOiJSUzI1NiIs...可解码出alg: "RS256"),但代码里硬编码用了HS256——两者完全不兼容:RS256是非对称加密(私钥签名、公钥验证),HS256是对称加密(同一密钥完成签名+验证)。
  2. 公钥使用错误:从Google获取的公钥数组是kid => 公钥内容的结构,你现在取的是$k[0](即kid字符串),而非对应的公钥内容,直接导致验证时密钥无效。

修正后的代码

public static function checkLogin(){
    $headers = apache_request_headers();

    // 从请求头中获取Bearer令牌,注意去掉多余引号
    $jwt = null;
    if (isset($headers['Authorization'])){
        $jwt = explode(' ', trim($headers['Authorization'], '"'))[1];
    } else if (isset($headers['authorization'])) {
        $jwt = explode(' ', trim($headers['authorization'], '"'))[1];
    }

    if (!$jwt) {
        die(json_encode(array("error" => true, "status" => 401, "message" => "NO TOKEN PROVIDED.")));
    }

    // 获取Google的Firebase签名公钥列表
    $publicKeys = file_get_contents('https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com');
    $publicKeys = json_decode($publicKeys, true);

    // 解析JWT头部,提取kid以匹配对应公钥
    list($headerEncoded) = explode('.', $jwt);
    // 修复Base64URL编码的兼容问题
    $header = json_decode(base64_decode(str_replace(['-', '_'], ['+', '/'], $headerEncoded)), true);
    $kid = $header['kid'] ?? null;

    if (!$kid || !isset($publicKeys[$kid])) {
        die(json_encode(array("error" => true, "status" => 401, "message" => "INVALID PUBLIC KEY.")));
    }

    JWT::$leeway = 60;
    try {
        // 使用RS256算法和匹配到的公钥验证令牌
        $decoded = JWT::decode($jwt, new Key($publicKeys[$kid], 'RS256'));
    } catch (Exception $e) {
        die(json_encode(array("error" => true, "status" => 401, "message" => "TOKEN VERIFICATION FAILED: " . $e->getMessage())));
    }

    $decoded_array = (array) $decoded;
    Utilities::debug($decoded_array);
    
    // JWT::decode已自动验证exp等字段,无需重复判断
    return $decoded_array['exp'];
}

关键说明

  • 算法修正:Firebase的ID Token固定使用RS256算法签名,必须用对应公钥验证,不能用HS256。
  • 公钥动态匹配:Google会定期轮换签名密钥,必须通过token中的kid字段匹配当前有效的公钥,不能固定取第一个。
  • 自动验证逻辑:JWT::decode会自动校验令牌的过期时间(exp)、签发时间(iat)等核心字段,验证失败直接抛出异常,无需手动判断。
  • 请求头处理:示例请求头中Authorization的值带双引号,需用trim去除,否则解析出的令牌会包含无效字符导致验证失败。

内容的提问来源于stack exchange,提问作者digitalway

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 07:53:12