remessage / json-web-token
A JSON Web Token (RFC 7519) 实现库
Requires
- php: >=8.3
- ext-json: *
- ext-mbstring: *
- ext-sodium: *
- doctrine/collections: ^2.1.4
- laminas/laminas-math: ^3.2
- paragonie/constant_time_encoding: ^2.3
- phpseclib/phpseclib: ^3.0
- psr/event-dispatcher: ^1.0.0
- psr/http-client: ^1.0.0
- psr/http-factory: ^1.0.0
- psr/log: ^3.0
- symfony/deprecation-contracts: ^3.0
- symfony/event-dispatcher: ^7.0
- symfony/serializer: ^7.0
Requires (Dev)
- bentools/cartesian-product: ^1.3
- friendsofphp/php-cs-fixer: ^3.8
- phpunit/phpunit: ^10.5
- predis/predis: ^2.2
- psalm/plugin-phpunit: ^0.18.4
- ramsey/uuid: ^4.7.5
- remessage/ruleset: ^1.0
- symfony/stopwatch: ^7.0
- vimeo/psalm: ^5.16
Suggests
- ext-memcache: To use memcache token storage
- laminas/laminas-math: To use Laminas Rand identifier generator
- predis/predis: To use redis token storage
- ramsey/uuid: To use UUID identifier generator
README
此库实现了与 JSON Web Token 相关的一系列标准,并被 Re: Message 库和服务(如 remessage/client
和 API 服务器)等所使用。
安装
您需要使用 Composer 来安装。运行以下命令
composer require remessage/json-web-token
用法
算法
所有令牌和服务使用算法对令牌数据进行签名、验证、加密和解密。每个算法必须实现 RM\Standard\Jwt\Algorithm\AlgorithmInterface
。
目前,我们只提供基于 HMAC 的算法
RM\Standard\Jwt\Algorithm\Signature\HMAC\HS256
用于基于 SHA-256 的 HMACRM\Standard\Jwt\Algorithm\Signature\HMAC\HS512
用于基于 SHA-512 的 HMACRM\Standard\Jwt\Algorithm\Signature\HMAC\HS3256
用于基于 SHA3-256(或 Keccak256)的 HMACRM\Standard\Jwt\Algorithm\Signature\HMAC\HS3512
用于基于 SHA3-512(或 Keccak512)的 HMAC
您还可以实现自己的算法。您需要实现 RM\Standard\Jwt\Algorithm\AlgorithmInterface
接口。
密钥
每个密钥必须实现 RM\Standard\Jwt\Key\Factory\KeyInterface
接口。
目前,我们支持以下类型
- 八位字节密钥
- 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\
命名空间中的负载声明。
您可以使用自定义属性。要创建自定义属性,您需要实现以下接口之一
RM\Standard\Jwt\Property\Header\HeaderParameterInterface
以创建自定义头部参数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;
实现
此库仅实现了服务平台正确运行所需的最小功能。