本次使用是在TP6 上实现
1. 使用composer 下载
类库地址:https://packagist.org/packages/lcobucci/jwt
composer命令:composer require lcobucci/jwt
使用说明地址:https://lcobucci-jwt.readthedocs.io/en/latest/
使用版本是:"lcobucci/jwt": "^4.1"
使用composer在php7.4版本下可能存在以下问题:
需要在php7.4中的php.ini中开启 extension=sodium
再次 :composer require lcobucci/jwt
2.代码片段:
<?php
namespace app\controller;
use Illuminate\Support\Facades\Date;
use Lcobucci\JWT\Configuration;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Signer\Key\InMemory;
use Lcobucci\JWT\UnencryptedToken;
use Lcobucci\JWT\Validation\RequiredConstraintsViolated;
/**
* Class JwtToken
* @package app\controller
* 这些是可用的设置器:
* setBuilderFactory(): 配置令牌构建器的创建方式
* setParser():配置自定义令牌解析器
* setValidator(): 配置自定义验证器
* setValidationConstraints(): 配置默认的验证约束集
* 检索组件:
* builder():检索令牌构建器(始终创建新实例)
* parser(): 检索令牌解析器
* signer(): 检索签名者
* signingKey(): 检索创建签名的密钥
* verificationKey(): 检索签名验证的密钥
* validator(): 检索令牌验证器
* validationConstraints(): 检索默认的验证约束集
*/
class JwtToken
{
private $config;
/**
* 构造初始化配置
* JwtToken constructor.
*/
public function __construct()
{
$config = Configuration::forSymmetricSigner(
// 您可以使用任何HMAC变体 (256, 384, and 512)
new Sha256(),
// 用您自己的密钥替换下面的值!这里使用CryptoKey来创建,地址:https://github.com/AndrewCarterUK/CryptoKey
// cryptokey generate / cryptokey generate --format=hex / cryptokey generate --entropy=64
InMemory::base64Encoded('rxZRlXZ9uyiznhlEO9OQYBVNcP+li+xer36XjFWBYWo=')
// 如果需要,您还可以在这里提供额外的参数来覆盖JOSE编码器/解码器
);
$this->config = $config;
}
/**
* @Method: 创建JWT
* @Author: CJH
* @DateTime: 2021/5/29 22:35
* @return string
*/
public function createToken($uid)
{
$config = $this->config;
assert($config instanceof Configuration);
// iss (issuer):签发人
// exp (expiration time):过期时间
// sub (subject):主题
// aud (audience):受众
// nbf (Not Before):生效时间
// iat (Issued At):签发时间
// jti (JWT ID):编号
$now = new \DateTimeImmutable();
$token = $config->builder()
// 配置颁发者(iss声明)
->issuedBy('http://example.com')
// 配置访问群体(aud声明)
->permittedFor('http://example.org')
// 配置id(jti声明)
->identifiedBy('1')
// 配置令牌发出的时间(iat声明)
->issuedAt($now)
// 配置可使用令牌的时间(nbf声明)
->canOnlyBeUsedAfter($now->modify('+1 minute'))
// 配置令牌的过期时间(exp claim)
->expiresAt($now->modify('+1 hour'))
// 配置一个名为“uid”的新声明
->withClaim('uid', $uid)
// 生成新令牌
->getToken($config->signer(), $config->signingKey());
// 创建令牌后,您就可以检索其数据并将其转换为字符串表示形式:
// $token->headers(); // Retrieves the token headers
// $token->claims(); // Retrieves the token claims
return $token->toString();
}
/**
* @Method: 解析token
* @Author: CJH
* @DateTime: 2021/5/29 22:35
* @param string $jwt
* @return string
*/
public function parseToken(string $jwt)
{
$config = $this->config;
assert($config instanceof Configuration);
$token = $config->parser()->parse(
$jwt
);
assert($token instanceof UnencryptedToken);
// 可通过以下获取信息
// $token->headers(); // Retrieves the token headers
// $token->claims(); // Retrieves the token claims
return $token->claims()->get('uid');
}
/**
* @Method: 验证令牌
* @Author: CJH
* @DateTime: 2021/5/29 23:37
* @param $jwt
* Lcobucci\JWT\Validation\Constraint\IdentifiedBy: 验证声明是否jti与预期值匹配
* Lcobucci\JWT\Validation\Constraint\IssuedBy: 验证声明iss是否被列为预期值
* Lcobucci\JWT\Validation\Constraint\PermittedFor: 验证声明是否aud包含预期值
* Lcobucci\JWT\Validation\Constraint\RelatedTo: 验证声明是否sub与预期值匹配
* Lcobucci\JWT\Validation\Constraint\SignedWith: 验证令牌是否使用预期的签名者和密钥签名
* Lcobucci\JWT\Validation\Constraint\StrictValidAt:验证存在及其有效性的权利要求中的iat,nbf和exp(支持余地配置)
* Lcobucci\JWT\Validation\Constraint\LooseValidAt: 验证声明iat, nbf, and exp, 当存在时(支持 leeway 配置)
* @return string
*/
public function validatorToken($jwt)
{
$config = $this->config;
$token = $config->parser()->parse($jwt);
assert($token instanceof UnencryptedToken);
$claims = $token->claims();
$jti = (string)$claims->get('jti');
$iss = (string)$claims->get('iss');
$aud = $claims->get('aud');
$nbf = $claims->get('nbf');
$exp = $claims->get('exp');
$now = new \DateTimeImmutable();
// 是否生效
if($nbf > $now){
return json_encode(array('data'=>'','msg'=>'未生效','code'=>0,'state'=>0));
}
// 是否过期
if($exp < $now){
return json_encode(array('data'=>'','msg'=>'已失效','code'=>0,'state'=>0));
}
//验证jwt id是否匹配
$validate_jwt_id = new \Lcobucci\JWT\Validation\Constraint\IdentifiedBy($jti);
// 验证签发人url是否正确
$validate_issued = new \Lcobucci\JWT\Validation\Constraint\IssuedBy($iss);
// 验证客户端url是否匹配
$validate_aud = new \Lcobucci\JWT\Validation\Constraint\PermittedFor($aud[0]);
// 需要注意这里!传入对应的验证数据
$config->setValidationConstraints($validate_jwt_id, $validate_issued, $validate_aud);
$constraints = $config->validationConstraints();
// 验证方法1
// try {
// $config->validator()->assert($token, ...$constraints);
// } catch (RequiredConstraintsViolated $e) {
// // list of constraints violation exceptions:
// var_dump($e->violations());
// }
// 验证方法2
if (!$config->validator()->validate($token, ...$constraints)) {
throw new \RuntimeException('No way!');
}
return json_encode(array('data'=>'','msg'=>'验证通过','code'=>1,'state'=>1));
}
}
3.使用
<?php
namespace app\controller;
use app\BaseController;
class Index extends BaseController
{
/**
* @Method: 创建JWT
* @Author: CJH
* @DateTime: 2021/5/30 21:05
* @return string
*/
public function createJWT()
{
$uid = input('param.uid');
$jwt = new JwtToken();
return $jwt->createToken($uid);
}
/**
* @Method: 从JWT中获取信息
* @Author: CJH
* @DateTime: 2021/5/30 21:05
* @return string
*/
public function parseJWT()
{
$token = input('post.jwt');
$jwt = new JwtToken();
return $jwt->parseToken($token);
}
/**
* @Method: 验证JWT是否合法
* @Author: CJH
* @DateTime: 2021/5/30 21:06
* @return int|string
*/
public function checkJWT(){
$token = input('post.jwt');
$jwt = new JwtToken();
return $jwt->validatorToken($token);
}
}
写在最后:
这只是记录JWT的简单使用,供学习参考,有关JWT的其他安全性等,请自行百度,谢谢!
可以相互交流学习一下哦。