weilewantieba / jwt
一个用于处理 JSON Web Token 和 JSON Web Signature 的简单库
v2.0
2023-01-04 02:23 UTC
Requires
- php: ^5.6 || ^8.0
- ext-mbstring: *
- ext-openssl: *
Requires (Dev)
- mikey179/vfsstream: ~1.5
- phpmd/phpmd: ~2.2
- phpunit/php-invoker: ~1.1
- phpunit/phpunit: ^5.7 || ^7.3
- squizlabs/php_codesniffer: ~2.3
This package is auto-updated.
Last update: 2024-09-04 06:10:26 UTC
README
一个用于处理 JSON Web Token 和 JSON Web Signature 的简单库(需要 PHP 5.6+)。实现基于RFC 7519。
安装
该软件包可在Packagist上找到,您可以使用Composer进行安装。
composer require weilewantieba/jwt
依赖关系
- PHP 5.6+
- OpenSSL 扩展
基本用法
创建
只需使用构建器创建新的 JWT/JWS 令牌
use Lcobucci\JWT\Builder; $time = time(); $token = (new Builder())->issuedBy('http://example.com') // Configures the issuer (iss claim) ->permittedFor('http://example.org') // Configures the audience (aud claim) ->identifiedBy('4f1g23a12aa', true) // Configures the id (jti claim), replicating as a header item ->issuedAt($time) // Configures the time that the token was issue (iat claim) ->canOnlyBeUsedAfter($time + 60) // Configures the time that the token can be used (nbf claim) ->expiresAt($time + 3600) // Configures the expiration time of the token (exp claim) ->withClaim('uid', 1) // Configures a new claim, called "uid" ->getToken(); // Retrieves the generated token $token->getHeaders(); // Retrieves the token headers $token->getClaims(); // Retrieves the token claims echo $token->getHeader('jti'); // will print "4f1g23a12aa" echo $token->getClaim('iss'); // will print "http://example.com" echo $token->getClaim('uid'); // will print "1" echo $token; // The string representation of the object is a JWT string (pretty easy, right?)
从字符串解析
使用解析器从 JWT 字符串创建新的令牌(以之前的令牌为例)
use Lcobucci\JWT\Parser; $token = (new Parser())->parse((string) $token); // Parses from a string $token->getHeaders(); // Retrieves the token header $token->getClaims(); // Retrieves the token claims echo $token->getHeader('jti'); // will print "4f1g23a12aa" echo $token->getClaim('iss'); // will print "http://example.com" echo $token->getClaim('uid'); // will print "1"
验证
我们可以轻松地验证令牌是否有效(以之前的令牌和时间为例)
use Lcobucci\JWT\ValidationData; $data = new ValidationData(); // It will use the current time to validate (iat, nbf and exp) $data->setIssuer('http://example.com'); $data->setAudience('http://example.org'); $data->setId('4f1g23a12aa'); var_dump($token->validate($data)); // false, because token cannot be used before now() + 60 $data->setCurrentTime($time + 61); // changing the validation time to future var_dump($token->validate($data)); // true, because current time is between "nbf" and "exp" claims $data->setCurrentTime($time + 4000); // changing the validation time to future var_dump($token->validate($data)); // false, because token is expired since current time is greater than exp // We can also use the $leeway parameter to deal with clock skew (see notes below) // If token's claimed time is invalid but the difference between that and the validation time is less than $leeway, // then token is still considered valid $dataWithLeeway = new ValidationData($time, 20); $dataWithLeeway->setIssuer('http://example.com'); $dataWithLeeway->setAudience('http://example.org'); $dataWithLeeway->setId('4f1g23a12aa'); var_dump($token->validate($dataWithLeeway)); // false, because token can't be used before now() + 60, not within leeway $dataWithLeeway->setCurrentTime($time + 51); // changing the validation time to future var_dump($token->validate($dataWithLeeway)); // true, because current time plus leeway is between "nbf" and "exp" claims $dataWithLeeway->setCurrentTime($time + 3610); // changing the validation time to future but within leeway var_dump($token->validate($dataWithLeeway)); // true, because current time - 20 seconds leeway is less than exp $dataWithLeeway->setCurrentTime($time + 4000); // changing the validation time to future outside of leeway var_dump($token->validate($dataWithLeeway)); // false, because token is expired since current time is greater than exp
重要
- 您必须配置
ValidationData
以告知您想验证的所有声明。 - 如果
ValidationData
包含未在令牌中使用或在ValidationData
中未配置的声明,则它们将被Token::validate()
忽略。 exp
、nbf
和iat
声明默认在ValidationData::__construct()
中配置为当前 UNIX 时间(time()
)。ValidationData
的可选$leeway
参数将导致我们在验证基于时间的声明时使用该数量的秒数。我们将“发行时间”(iat
)和“不可用时间”(nbf
)声明假定为未来,将“过期时间”(exp
)声明假定为过去。这允许在签发服务器的时间与验证服务器的时间不同的情况下进行操作,如RFC 7519 4.1 节中所述。
令牌签名
我们可以使用签名来验证令牌在生成后是否未被修改。此库实现了 Hmac、RSA 和 ECDSA 签名(使用 256、384 和 512)。
重要
不要允许发送给解析器的字符串决定使用哪种签名算法,否则您的应用程序将容易受到关键的 JWT 安全漏洞的影响。
下面的示例是安全的,因为 Signer
的选择是硬编码的,不能被恶意用户影响。
Hmac
Hmac 签名非常简单易用
use Lcobucci\JWT\Builder; use Lcobucci\JWT\Signer\Key; use Lcobucci\JWT\Signer\Hmac\Sha256; $signer = new Sha256(); $time = time(); $token = (new Builder())->issuedBy('http://example.com') // Configures the issuer (iss claim) ->permittedFor('http://example.org') // Configures the audience (aud claim) ->identifiedBy('4f1g23a12aa', true) // Configures the id (jti claim), replicating as a header item ->issuedAt($time) // Configures the time that the token was issue (iat claim) ->canOnlyBeUsedAfter($time + 60) // Configures the time that the token can be used (nbf claim) ->expiresAt($time + 3600) // Configures the expiration time of the token (exp claim) ->withClaim('uid', 1) // Configures a new claim, called "uid" ->getToken($signer, new Key('testing')); // Retrieves the generated token var_dump($token->verify($signer, 'testing 1')); // false, because the key is different var_dump($token->verify($signer, 'testing')); // true, because the key is the same
RSA 和 ECDSA
RSA 和 ECDSA 签名基于公钥和私钥,因此您必须使用私钥生成并使用公钥验证
use Lcobucci\JWT\Builder; use Lcobucci\JWT\Signer\Key; use Lcobucci\JWT\Signer\Rsa\Sha256; // you can use Lcobucci\JWT\Signer\Ecdsa\Sha256 if you're using ECDSA keys $signer = new Sha256(); $privateKey = new Key('file://{path to your private key}'); $time = time(); $token = (new Builder())->issuedBy('http://example.com') // Configures the issuer (iss claim) ->permittedFor('http://example.org') // Configures the audience (aud claim) ->identifiedBy('4f1g23a12aa', true) // Configures the id (jti claim), replicating as a header item ->issuedAt($time) // Configures the time that the token was issue (iat claim) ->canOnlyBeUsedAfter($time + 60) // Configures the time that the token can be used (nbf claim) ->expiresAt($time + 3600) // Configures the expiration time of the token (exp claim) ->withClaim('uid', 1) // Configures a new claim, called "uid" ->getToken($signer, $privateKey); // Retrieves the generated token $publicKey = new Key('file://{path to your public key}'); var_dump($token->verify($signer, $publicKey)); // true when the public key was generated by the private one =)
重要的是要说明,如果您正在使用 RSA 密钥,则不应调用 ECDSA 签名者(反之亦然),否则 sign()
和 verify()
将引发异常!