remessage/json-web-token

A JSON Web Token (RFC 7519) 实现库

v0.7.1 2023-12-02 19:24 UTC

README

Version PHP Version Support License GitHub Workflow Status

此库实现了与 JSON Web Token 相关的一系列标准,并被 Re: Message 库和服务(如 remessage/client 和 API 服务器)等所使用。

安装

您需要使用 Composer 来安装。运行以下命令

composer require remessage/json-web-token

用法

算法

所有令牌和服务使用算法对令牌数据进行签名、验证、加密和解密。每个算法必须实现 RM\Standard\Jwt\Algorithm\AlgorithmInterface

目前,我们只提供基于 HMAC 的算法

  1. RM\Standard\Jwt\Algorithm\Signature\HMAC\HS256 用于基于 SHA-256 的 HMAC
  2. RM\Standard\Jwt\Algorithm\Signature\HMAC\HS512 用于基于 SHA-512 的 HMAC
  3. RM\Standard\Jwt\Algorithm\Signature\HMAC\HS3256 用于基于 SHA3-256(或 Keccak256)的 HMAC
  4. RM\Standard\Jwt\Algorithm\Signature\HMAC\HS3512 用于基于 SHA3-512(或 Keccak512)的 HMAC

您还可以实现自己的算法。您需要实现 RM\Standard\Jwt\Algorithm\AlgorithmInterface 接口。

密钥

每个密钥必须实现 RM\Standard\Jwt\Key\Factory\KeyInterface 接口。

目前,我们支持以下类型

  1. 八位字节密钥
  2. RSA 密钥(PSS 和 PKCS1)(仅限签名)

您还可以实现自己的密钥。您需要实现 RM\Standard\Jwt\Key\Factory\KeyFactoryInterface 接口以从数组创建密钥。如果您的密钥包含此库中未实现的属性,则还需要实现 RM\Standard\Jwt\Key\Parameter\KeyParameterInterface 接口并使用 RM\Standard\Jwt\Key\Parameter\Factory\ParameterFactory 与您的密钥参数类一起使用。

令牌

要创建新令牌,您可以使用 RM\Standard\Jwt\Signature\SignatureToken 类。该类的构造函数有 3 个参数:头部参数、负载声明和签名。头部参数必须包含算法参数。其他参数是可选的。

示例

<?php

use RM\Standard\Jwt\Algorithm\Signature\HMAC\HS3256;
use RM\Standard\Jwt\Property\Header\Algorithm;
use RM\Standard\Jwt\Signature\SignatureToken;

$algorithm = new HS3256();
$token = new SignatureToken([Algorithm::fromAlgorithm($algorithm)]);

通过次级构造函数

<?php

use RM\Standard\Jwt\Algorithm\Signature\HMAC\HS3256;
use RM\Standard\Jwt\Signature\SignatureToken;

$token = SignatureToken::createWithAlgorithm(new HS3256());

属性

令牌有称为属性的参数,这些是重要的敏感数据,用于授权和验证。它们分别位于令牌的头部和负载中。头部参数包含常见的令牌数据:签名或加密算法和令牌类型。负载声明包含验证所需的数据:令牌签名/加密时间、操作时间、签名者和为谁签名。负载还可以包含业务逻辑数据,如权限或其他内容。

定义在 RM\Standard\Jwt\Property\Header\ 命名空间中的头部参数。定义在 RM\Standard\Jwt\Property\Payload\ 命名空间中的负载声明。

您可以使用自定义属性。要创建自定义属性,您需要实现以下接口之一

  1. RM\Standard\Jwt\Property\Header\HeaderParameterInterface 以创建自定义头部参数
  2. RM\Standard\Jwt\Property\Payload\ClaimInterface 以创建自定义声明

根据标准,属性名称必须足够简洁。我们使用 3 个字符的名称,但没有限制。

序列化

由某些服务实现的令牌序列化实现了 RM\Standard\Jwt\Serializer\SerializerInterface 接口。

示例

<?php

use RM\Standard\Jwt\Serializer\SignatureCompactSerializer;
use RM\Standard\Jwt\Signature\SignatureToken;

// serialized token
// {"alg": "HS256","typ": "JWT"} . {"sub": "1234567890","name": "John Doe","iat": 1516239022} . signature
$rawToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c';

$serializer = new SignatureCompactSerializer();

// result is a SignatureToken object
// serializer DO NOT validate token
$token = $serializer->deserialize($rawToken);

// will return true
var_dump($rawToken === $token->toString($serializer));

签名

要签名令牌,您应使用 RM\Standard\Jwt\Signature\Signer。签名者仅依赖于序列化器,但默认为 RM\Standard\Jwt\Serializer\SignatureCompactSerializer

序列化器对于服务进行令牌签名是必要的,因为签名是由密钥签名的头部和有效载荷。

此外,您还可以使用装饰器为签名者提供一些令牌处理功能。

  • RM\Standard\Jwt\Signature\GeneratedSigner提供在签名前生成令牌属性的能力。
  • RM\Standard\Jwt\Signature\EventfulSigner创建事件。
  • RM\Standard\Jwt\Signature\LoggableSigner允许收集关于签名过程的日志。

示例

<?php

use Laminas\Math\Rand;
use ParagonIE\ConstantTime\Base64UrlSafe;
use RM\Standard\Jwt\Algorithm\Signature\HMAC\HS3256;
use RM\Standard\Jwt\Key\Key;
use RM\Standard\Jwt\Key\Parameter\Type;
use RM\Standard\Jwt\Key\Parameter\Value;
use RM\Standard\Jwt\Signature\SignatureToken;
use RM\Standard\Jwt\Signature\Signer;

// some algorithm
$algorithm = new HS3256();
$token = SignatureToken::createWithAlgorithm($algorithm);

// generate random octet key for example
$value = Base64UrlSafe::encode(Rand::getBytes(64));
$key = new Key(
    [
        new Type(Type::OCTET),
        new Value($value),
    ]
);

$signer = new Signer();
// method returns new token object with signature
$signedToken = $signer->sign($token, $algorithm, $key);

// will return something like this:
// eyJhbGciOiJIUzMyNTYiLCJ0eXAiOiJKV1QifQ.W10.KDa2nZVCuX1LldcMJZz2wp_QifjN7sNHCFLtGDAWF9s
echo $signedToken;

实现

此库仅实现了服务平台正确运行所需的最小功能。

将不会实现

  • 嵌套JSON Web Token
  • JWS和JWE的多个签名
  • JWS JSON序列化(RFC 7515,第7.2节)
  • JWE JSON序列化(RFC 7516,第7.2节)