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

如何使用JWS Detached验证HTTP消息 解决firebase/jwt校验失败问题

问题根源

你当前校验失败的核心原因是Detached JWS的 payload 被分离到了HTTP请求体中,你拿到的x-sign-jws参数只有JWS头和签名段(两个.中间为空),直接调用JWT::decode缺少了待校验的payload部分。


分步解决方案

1. 实现Base64URL编码逻辑

Base64URL和标准Base64的区别是:将+替换为-、/替换为_、删除末尾的=填充符,PHP实现代码如下:

function base64url_encode(string $data): string
{
    return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}

2. 获取原始HTTP请求体

直接读取PHP输入流拿到和发送端完全一致的原始请求体,不要用$_POST(会被解析修改):

$raw_body = file_get_contents('php://input');

3. 拼接完整JWS串

你拿到的x-sign-jws格式为[JWS头].[空payload].[签名],把Base64URL编码后的请求体填入空payload位置,得到完整JWS:

// 读取签名头
$headers = getallheaders();
$received_jws = $headers['X-Sign-Jws'] ?? '';
list($jws_header, $empty_payload, $jws_signature) = explode('.', $received_jws);
// 编码请求体
$encoded_body = base64url_encode($raw_body);
// 拼接完整JWT串
$complete_jwt = implode('.', [$jws_header, $encoded_body, $jws_signature]);

4. 调用firebase/jwt校验

注意你原来的校验算法参数写错了,第三个参数只需传入支持的算法数组['HS256']即可:

use Firebase\JWT\JWT;
use Firebase\JWT\Key;

$secret_key = '12345678'; // 替换为你的实际密钥
try {
    $decoded = JWT::decode($complete_jwt, new Key($secret_key, 'HS256'));
    // 校验通过,执行后续业务逻辑
} catch (\Exception $e) {
    // 校验失败,返回401错误
    http_response_code(401);
    exit('签名校验失败');
}

注意事项

  • 必须使用原始请求体进行编码,不能做任何解码、修改操作,要和发送端签名时使用的请求体完全一致
  • 如果发送端签名时包含了指定请求头参数,需要额外把对应请求头按规则拼入待签名内容,和发送端逻辑对齐
  • 密钥编码要保持和发送端一致,默认使用UTF-8编码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 04:42:03