<?php namespace app\service; use DateTimeImmutable; use DateTimeZone; use Exception; use Lcobucci\Clock\SystemClock; use Lcobucci\JWT\Configuration; use Lcobucci\JWT\Signer\Hmac\Sha256; use Lcobucci\JWT\Signer\Key\InMemory; use Lcobucci\JWT\UnencryptedToken; use Lcobucci\JWT\Validation\Constraint\IssuedBy; use Lcobucci\JWT\Validation\Constraint\LooseValidAt; use Lcobucci\JWT\Validation\Constraint\PermittedFor; use Lcobucci\JWT\Validation\Constraint\ValidAt; class Jwt { private static $secret = 'lF9XkOMfpsR0ODVfbasY2HtDrIps8GIX'; private static $expire = 86400 * 3;//秒 private static $iss = 'dxtc';//jwt签发者 private static $sub = 'dxtc-customer';//jwt所面向的用户 private static $aud = 'dxtc-customer';//接受jwt的一方 private static function config(): Configuration { return Configuration::forSymmetricSigner( // You may use any HMAC variations (256, 384, and 512) new Sha256(), // replace the value below with a key of your own! InMemory::base64Encoded(self::$secret) // You may also override the JOSE encoder/decoder if needed by providing extra arguments here ); } /** * 获取token有效期 单位秒 * * @return int */ public static function expire(): int { return self::$expire; } /** * 编码 * * @param $data * @param int $expire * @return string * @throws Exception */ public static function generate($data, int $expire = 0): string { $expire = $expire <= 0 ? self::$expire : $expire; $now = new DateTimeImmutable('now', new DateTimeZone('Asia/ShangHai')); $token = self::config()->builder() // Configures the issuer (iss claim) ->issuedBy(self::$iss) // Configures the audience (aud claim) ->permittedFor(self::$aud) // Configures the id (jti claim) // ->identifiedBy($this->jti) // Configures the time that the token was issue (iat claim) ->issuedAt($now) // Configures the expiration time of the token (exp claim) ->expiresAt($now->modify(sprintf('+%d seconds', $expire))) // Configures a new claim, called "uid" ->withClaim('data', $data) // Configures a new header, called "foo" // ->withHeader('foo', 'bar') // Builds a new token ->getToken(self::config()->signer(), self::config()->signingKey()); return $token->toString(); } /** * 解析 * * @param string $tokenStr * @return array|mixed */ public static function parse(string $tokenStr) { $config = self::config(); try { $token = $config->parser()->parse($tokenStr); assert($token instanceof UnencryptedToken); return $token->claims()->all()['data'] ?? []; } catch (Exception $e) { return []; } } /** * 验证token * * @param string $tokenStr * @return bool */ public static function validate(string $tokenStr): bool { $config = self::config(); try { $token = $config->parser()->parse($tokenStr); assert($token instanceof UnencryptedToken); //验证签发人iss是否正确 $validateIssued = new IssuedBy(self::$iss); $config->setValidationConstraints($validateIssued); //验证客户端aud是否匹配 $validateAud = new PermittedFor(self::$aud); $config->setValidationConstraints($validateAud); //验证是否过期 exp $timezone = new DateTimeZone('Asia/Shanghai'); $now = new SystemClock($timezone); $validateExpired = new LooseValidAt($now); $config->setValidationConstraints($validateExpired); $constraints = $config->validationConstraints(); return $config->validator()->validate($token, ...$constraints); } catch (Exception $e) { return false; } } }