ignislabs/hotjot

无装饰的JWT库

1.0.0 2017-11-22 21:28 UTC

This package is not auto-updated.

Last update: 2024-09-15 01:57:48 UTC


README

Build Status Version License

无装饰的JWT & JWS库。

安装

使用composer安装

$ composer require ignislabs/hotjot

要求

  • PHP >= 7.1
  • OpenSSL扩展
  • JSON扩展

用法

创建、验证和验证令牌非常简单,在我们深入到每个组件的详细信息之前,让我们先快速看一下这些操作。

创建令牌

$token = $factory->create($claims, $headers);

验证令牌

$signer->verify($token);

验证令牌

$validator->validate($token);

让我们首先看看签名者,因为这是库中最重要的部分。您需要一个签名者来创建已签名的令牌并验证它们。

签名者

您可以选择使用 HMACRSANone 签名者。

HMAC 签名者

HMAC是最简单的一种。它是一个对称算法,这意味着您只有一个私钥。您应该尽量使其在密码学上尽可能安全和随机。

您有3种不同的选项:HS256HS384HS512。所有这三种都需要将加密密钥作为构造函数参数。

$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种不同的选项:RS256RS384RS512。所有这三种都需要私钥和公钥,以及如果您的私钥受保护,则需要密码。

$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对象,同样iatnbf也返回。

如果您出于某种原因需要使用不同的签名者,可以这样做

$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