ignislabs / hotjot
无装饰的JWT库
Requires
- php: >=7.1
- ext-json: *
- ext-openssl: *
Requires (Dev)
- phpspec/phpspec: ^4.1
This package is not auto-updated.
Last update: 2024-09-15 01:57:48 UTC
README
无装饰的JWT & JWS库。
安装
使用composer安装
$ composer require ignislabs/hotjot
要求
- PHP >= 7.1
- OpenSSL扩展
- JSON扩展
用法
创建、验证和验证令牌非常简单,在我们深入到每个组件的详细信息之前,让我们先快速看一下这些操作。
创建令牌
$token = $factory->create($claims, $headers);
验证令牌
$signer->verify($token);
验证令牌
$validator->validate($token);
让我们首先看看签名者,因为这是库中最重要的部分。您需要一个签名者来创建已签名的令牌并验证它们。
签名者
您可以选择使用 HMAC
、RSA
或 None
签名者。
HMAC
签名者
HMAC是最简单的一种。它是一个对称算法,这意味着您只有一个私钥。您应该尽量使其在密码学上尽可能安全和随机。
您有3种不同的选项:HS256
、HS384
和 HS512
。所有这三种都需要将加密密钥作为构造函数参数。
$signer = new \IgnisLabs\HotJot\Signer\HMAC\HS512('encryption key');
RSA
签名者
RSA是非对称的,这意味着您需要创建一个密钥对
# create a strong, password protected private key $ openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -outform PEM -out private.pem -pass stdin # get public key $ openssl rsa -pubout -in private.pem -out public.pem
如果您不想生成密码保护的密钥,只需省略 -pass stdin
。
如果您需要/想要,可以使您的公钥公开可用,这样任何人都可以使用它来验证令牌是否真的由您签名(这就是公开密钥密码学背后的一个目的)。
同样,您有3种不同的选项:RS256
、RS384
和 RS512
。所有这三种都需要私钥和公钥,以及如果您的私钥受保护,则需要密码。
$privateKey = file_get_contents('/path/to/private.pem'); $publicKey = file_get_contents('/path/to/public.pem'); $signer = new \IgnisLabs\HotJot\Signer\RSA\RS512($privateKey, $publicKey, 'key passphrase (if any)');
私钥用于签名,公钥用于验证。
None
签名者
使用 None
签名者将导致没有签名的不安全令牌,并且使用此签名者进行验证将始终失败,因为不安全令牌是没有签名的。
警告!尽管技术上可以创建不安全令牌,但您应该非常小心,并且非常清楚您正在做什么。
此签名者不需要任何参数,因为它不能签名或验证。它始终返回一个空字符串作为签名,验证始终失败。
$signer = new \IgnisLabs\HotJot\Signer\None;
令牌创建
现在您已经了解了签名者,让我们看看您如何创建令牌。
要创建令牌,您需要Factory
和一个Signer
,然后您将得到一个带有一些方便方法的Token
对象。
创建安全令牌
要创建安全令牌,请使用除None
之外的所有签名者。
$signer = new \IgnisLabs\HotJot\Signer\HMAC\HS512('encryption key'); $factory = new \IgnisLabs\HotJot\Factory($signer); $token = $factory->create([ 'iss' => 'http://api.example.com', 'aud' => 'http://www.example.com', 'jti' => bin2hex(random_bytes(16)), 'exp' => (new DateTime('+10 days'))->getTimestamp(), // etc... ]); $token->getHeader('alg'); // -> 'HS512' $token->getClaim('iss'); // -> 'http://api.example.com' $token->getClaim('exp'); // -> DateTime object
如您所见,exp
返回一个DateTime
对象,同样iat
和nbf
也返回。
如果您出于某种原因需要使用不同的签名者,可以这样做
$newFactory = $factory->setSigner($anotherSigner);
工厂是不可变的,因此当您这样做时,当前工厂实例不会被修改,而是返回一个新的实例,带有新的签名者。
这非常有用,当您想要临时更改特殊用例的签名时。
创建不安全令牌
要创建不安全令牌,您需要使用None
签名者。
警告!尽管技术上可以创建不安全令牌,但您应该非常小心,并且非常清楚您正在做什么。(是的,我知道我在重复:P)
$signer = new \IgnisLabs\HotJot\Signer\None; $factory = new \IgnisLabs\HotJot\Factory($signer); $token = $factory->create([ 'iss' => 'http://api.example.com', 'aud' => 'http://www.example.com', 'jti' => bin2hex(random_bytes(16)), 'exp' => (new DateTime('+10 days'))->getTimestamp(), // etc... ]); $token->getClaim('alg'); // -> 'none' $token->getSignature(); // -> null
解析
您可以使用解析器解析编码的令牌字符串。您如何获得编码的令牌超出了库的范围(授权头、查询参数等)。
当你解析一个编码令牌时,你会得到一个Token
对象,与使用Factory
得到的是同一个。
$parser = new \IgnisLabs\HotJot\Parser; $token = $parser->parse($encodedTokenString);
解析器不会验证或校验令牌,只要它能解析且符合rfc规范,解析器就会成功并返回令牌对象。你需要使用签名者和校验者来验证和校验令牌。
如果解析器失败,它将抛出一个带有适当信息的InvalidTokenException
异常。
签名验证
这是接收外部世界令牌时的关键步骤。
此库不会自动根据alg
头设置任何算法,你也不应该这样做。遵循这个简单的规则,你可以避免已知的漏洞。
此库通过要求你自己实例化所需的签名者,并通过在实例化时传递密钥而不是在验证时传递密钥,将密钥与签名者建立硬关联,从而使得避免此类攻击变得简单,减少了出错的机会。
所有签名者首先会检查令牌的alg
头,并检查它是否与签名者的算法匹配。如果算法不匹配,它将抛出SignatureVerificationException
异常。
$signer = new \IgnisLabs\HotJot\Signer\RSA\RS512($privateKey, $publicKey, 'passphrase'); $signer->verify($token); // -> boolean — $token most likely obtained through the parser
校验
一旦你有一个验证过的令牌,你就可以开始使用Validator
来校验它。
Validator
是一个非常简单的类,它接受一些令牌校验器,并使用它们来校验一个令牌。校验器在失败时不会返回任何值,而是抛出异常。
此库已经包含了一些有用的校验器,但你可以添加任意多的校验器。
use IgnisLabs\HotJot\Validators as 🕵; $validator = new \IgnisLabs\HotJot\Validator( new 🕵\IssuedAtValidator, // fails if token used before `iat` new 🕵\NotBeforeValidator, // fails if token used before `nbf` new 🕵\ExpiresAtValidator // fails if token is used after `exp` ); $validator->validate($token);
如果你想让这些校验器中的任何一个成为必需的,你可以这样实例化它们
use IgnisLabs\HotJot\Validators as 🕵; $validator = new \IgnisLabs\HotJot\Validator( new 🕵\IssuedAtValidator(true), new 🕵\NotBeforeValidator(true), new 🕵\ExpiresAtValidator(true) ); $validator->validate($token);
你可以创建自己的校验器,只需让它们实现IgnisLabs\HotJot\Contracts\TokenValidator
接口。你还拥有\IgnisLabs\HotJot\Validators\ClaimRequiredTrait
,在创建必需的校验器时可以节省一些时间。
算法
✔️ none
✔️ HS256
✔️ HS384
✔️ HS512
✔️ RS256
✔️ RS384
✔️ RS512
🔲 ES256
🔲 ES384
🔲 ES512