
本文详解如何纯原生 PHP 实现 HS512 算法 JWT 的生成,重点纠正常见的签名错误——必须对 HMAC-SHA512 的二进制输出进行 Base64URL 编码,而非十六进制字符串。
本文详解如何纯原生 php 实现 hs512 算法 jwt 的生成,重点纠正常见的签名错误——必须对 hmac-sha512 的**二进制输出**进行 base64url 编码,而非十六进制字符串。
JWT(JSON Web Token)由三部分组成:Header、Payload 和 Signature,以英文句点 . 拼接。其中 Signature 是对 base64url(header) + '.' + base64url(payload) 使用密钥进行 HMAC-SHA512 签名后,再经 Base64URL 编码得到的值。
关键误区在于:PHP 的 hash_hmac() 函数默认返回十六进制字符串($raw_output = false),但 JWT 规范要求签名必须基于 原始二进制摘要(raw binary digest) 进行 Base64URL 编码。若传入 false,得到的是 128 字符的十六进制字符串(如 f1b7227d6f1ab87e...),再编码会导致签名无效;而传入 true 才返回 64 字节的原始二进制数据,这才是正确输入。
以下是完整、可直接运行的实现代码:
function gen_jwt(): string
{
$signing_key = "changeme"; // 生产环境请使用 cryptographically secure secret(如 random_bytes(32))
// Header: 必须包含 alg 和 typ
$header = [
"alg" => "HS512",
"typ" => "JWT"
];
$header = base64_url_encode(json_encode($header, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
// Payload: 示例含 exp=0(已过期,仅用于测试)
$payload = [
"exp" => 0,
"iat" => time(),
"jti" => bin2hex(random_bytes(16)) // 可选:唯一令牌标识
];
$payload = base64_url_encode(json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
// ✅ 正确签名步骤:third parameter $raw_output = true
$signature = hash_hmac('sha512', "$header.$payload", $signing_key, true);
$signature = base64_url_encode($signature);
return "$header.$payload.$signature";
}
function base64_url_encode(string $data): string
{
return str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($data));
}
✅ 验证方式:将生成的 JWT 粘贴至 jwt.io Debugger —— 若 Header 与 Payload 解析正常,且 Signature 显示 “Signature Verified”,即表示完全合规。
注意事项:
-
base64_url_encode()必须严格替换+→-、/→_、去除末尾=,不可使用普通base64_encode()直接拼接; -
json_encode()建议添加JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES标志,避免特殊字符转义导致签名不一致; - 密钥
$signing_key应具备足够熵(推荐random_bytes(32)生成并安全存储),切勿硬编码于生产代码中; - 此实现未包含签名校验逻辑;如需验证,需用相同密钥对前两段重新计算签名并比对(注意恒时比较防时序攻击)。
掌握这一底层原理,不仅可脱离库实现轻量 JWT,更能深入理解 JWT 安全机制的本质:签名的有效性完全取决于是否严格遵循 RFC 7519 的编码与哈希规范。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











