JWT 签名未在 PHP 中验证

Posted

技术标签:

【中文标题】JWT 签名未在 PHP 中验证【英文标题】:JWT signature not verifying in PHP 【发布时间】:2016-12-27 00:55:30 【问题描述】:

我刚刚开始使用基于令牌的身份验证,并编写了一个非常简单的 php 脚本来创建 JWT。但是,当我在 jwt.io 的调试器中运行它时,签名永远不会验证。

JWT.io

    $secret = "super_secure_private_key";

    function base64url_encode($data) 
        return rtrim(strtr(base64_encode($data), "+/", "-_"), "=");
    

    $header = base64url_encode(json_encode([
        "alg" => "HS256",
        "typ" => "JWT"
    ]));

    $payload = base64url_encode(json_encode([
        "name" => "James Walker",
        "privileges" => "total"
    ]));

    $signature = base64url_encode(hash_hmac("sha256", $header . "." . $payload, $secret));

    $token = $header . "." . $payload . "." . $signature;

据我所知,我的实现与 JWT 的格式一致。我错过了什么,或者我应该使用图书馆,例如php-jwt 生成新令牌并验证它们?

对于我的使用,我的实现可能无论如何都可以正常工作,因为我仍然可以使用相同的代码自己验证令牌。但我只是不确定为什么 jwt.io 不验证签名。

【问题讨论】:

【参考方案1】:

当我第一次编写 JWT 实现时,这个问题让我很头疼。诀窍是创建签名的键控散列必须输出原始二进制数据,但hash_hmac 的默认设置并非如此。

更改生成签名的方式:

hash_hmac("sha256", $header . "." . $payload, $secret);

hash_hmac("sha256", $header . "." . $payload, $secret, true);

查看最后一个参数in the manual的信息:

raw_output:设置为 TRUE 时,输出原始二进制数据。错误输出 小写十六进制

【讨论】:

非常感谢!它现在可以工作,我所有的签名都会验证。非常感谢。 @Ilmiont 快乐编码

以上是关于JWT 签名未在 PHP 中验证的主要内容,如果未能解决你的问题,请参考以下文章

JWT 签名验证失败,java 到 php

谷歌 OAuth JWT 签名验证

JWT/OAuth 令牌签名验证失败

签名验证失败 - Apple 使用 Firebase JWT 登录

ES256 JWT 在 PHP 中为 Apple AppStoreConenct API 身份验证签名

使用 PHP 从 login.microsoftonline.com 验证 JWT 中的签名