使用相同的密钥获取不同的 JWT 令牌

Getting different JWT tokens with the same key

我是 JWT 令牌的新手,我正在尝试从 jwt 令牌获取信息。问题是当我是生成令牌的人时没有问题,但是由于某种原因,当我使用完全相同的信息在 JWT.io 生成令牌时,令牌是不同的,因此,验证失败。我想问题可能出在我使用的密钥上,因为当使用像“HELLO”这样的简单密钥时,这种差异不会发生。这是我的代码:

<?php
namespace App\Controller\Component;

use Cake\Controller\Component;
use \Firebase\JWT\JWT;
use Cake\ORM\TableRegistry;

class JWTComponent extends Component
{
    public function check_token($token){
        $decoded = [];
         $key = openssl_pkey_get_details(openssl_pkey_get_private('file://'.APP.'private.pem'))['key'];
       
        try {
            $decoded = JWT::decode($token, $key, array('HS256'));
            $decoded = (array) $decoded;
        } catch (Exception $e) {
            $decoded = ['error' => $e->getMessage()];
        }finally{
            return $decoded;
        }
    }

    public function get_token($data) {
        $key = openssl_pkey_get_details(openssl_pkey_get_private('file://'.APP.'private.pem'))['key'];
        return JWT::encode($data, $key);
    }
}

你的直觉很好。通过检查签名来验证令牌的完整性。令牌由发行方签名。您可以使用不同的算法来签署这些令牌。正如@jps 指出的那样,您可以拥有对称和非对称签名。在对称签名中,相同的密钥用于签名和验证密钥。 HS256 是一种对称签名算法。您可以使用证书来做到这一点(就像在您的代码中一样),但我认为这有点矫枉过正。无论如何,如果您希望在 JWT.io 处生成的密钥在您的代码中有效,您必须将私钥粘贴到 JWT.io 中,以便它可以用于签名。然后令牌应该在您的代码中有效。这就是当您使用简单的字符串作为键时它起作用的原因。

您在代码中生成的令牌和在 JWT.io 中生成的令牌最终可能看起来有些不同。也就是说,它们都是长字符串,三部分由点分隔,但字符串不必相等。这并不意味着这是一个不同的令牌。编码的 JWT 可能会有所不同,具体取决于您是否在输入中使用了换行符,或者您使用了多少空格。尽管经过编码的最终 JWT 可能看起来不同,但这些标记仍然具有相同的值。如果你解码它们,你会得到相同的 JSON,可能格式略有不同。

至于对称算法的使用,通常使用非对称签名会更好,所以如果您可以使用该选项,我绝对会推荐它。另外,看看 PHP 的一些库来发布和验证 JWT,除非你编写代码来了解更多关于 JWT 本身的信息。您可以在 JWT.io.

上找到图书馆列表

如果您计划使用 JWT 保护 API,请查看我写的这篇 security best practices 文章,了解 JWT 的注意事项。