132 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			PHP
		
	
	
		
		
			
		
	
	
			132 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			PHP
		
	
	
|  | <?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\PermittedFor; | ||
|  | use Lcobucci\JWT\Validation\Constraint\ValidAt; | ||
|  | 
 | ||
|  | class Jwt | ||
|  | { | ||
|  |     private static $secret = 'lF9XkOMfpsR0ODVfbasY2HtDrIps8GIX'; | ||
|  |     private static $expire = 7200 * 10;//秒
 | ||
|  |     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 ValidAt($now); | ||
|  |             $config->setValidationConstraints($validateExpired); | ||
|  | 
 | ||
|  |             $constraints = $config->validationConstraints(); | ||
|  | 
 | ||
|  |             return $config->validator()->validate($token, ...$constraints); | ||
|  |         } catch (Exception $e) { | ||
|  |             return false; | ||
|  |         } | ||
|  |     } | ||
|  | } |