JWT - PHP Online

Form of PHP Sandbox

Enter Your PHP code here for testing/debugging in the Online PHP Sandbox. As in the usual PHP files, you can also add HTML, but do not forget to add the tag <?php in the places where the PHP script should be executed.



Your result can be seen below.

Result of php executing





Full code of JWT.php

  1. <?php
  2.  
  3. class Jwt
  4. {
  5. //头部
  6.     private $header = array(
  7.         'alg' => 'HS256', //生成signature的算法
  8.         'typ' => 'JWT'  //类型
  9.     );
  10.  
  11.     //使用HMAC生成信息摘要时所使用的密钥
  12.     private $key = 'jjpj-3#^*';
  13.  
  14.     private $time = 0;
  15.  
  16.         private $payload = [];
  17.     public function setExpire(int $expire): Jwt
  18.     {
  19.         $this->expire = $expire;
  20.         return $this;
  21.     }
  22.  
  23.     /**
  24.      * 获取时间
  25.      * @return int
  26.      */
  27.     private function getTime(): int
  28.     {
  29.         return time();
  30.     }
  31.  
  32.     public function __construct()
  33.     {
  34.         $this->time = $this->getTime();
  35.     }
  36.  
  37.  
  38.     public function setKey(string $key): Jwt
  39.     {
  40.         $this->key = $key;
  41.         return $this;
  42.     }
  43.  
  44.     /**
  45.      * 获取jwt token
  46.      * @param array $payload jwt载荷  格式如下非必须
  47.      * [
  48.      * 'iss'=>'jwt_admin', //该JWT的签发者
  49.      * 'iat'=>time(), //签发时间
  50.      * 'exp'=>time()+7200, //过期时间
  51.      * 'nbf'=>time()+60, //该时间之前不接收处理该Token
  52.      * 'sub'=>'www.admin.com', //面向的用户
  53.      * 'jti'=>md5(uniqid('JWT').time()) //该Token唯一标识
  54.      * ]
  55.      * @return string
  56.      * @throws Exception
  57.      */
  58.     public function generate(array $payload): string
  59.     {
  60.         if (!isset($payload['iss'])) {
  61.             $payload['iss'] = 'API v.1';
  62.         }
  63.                 if (!isset($payload['sub'])) {
  64.             $payload['sub'] = 'apiAuth';
  65.         }
  66.                 if (!isset($payload['aud'])) {
  67.             $payload['aud'] = 'HOST';
  68.         }
  69.                 if (!isset($payload['exp'])) {
  70.             $payload['exp'] = $this->getTime() + 60;
  71.         }
  72.                 if (!isset($payload['nbf'])) {
  73.             $payload['nbf'] = $this->getTime();
  74.         }
  75.                 if (!isset($payload['iat'])) {
  76.             $payload['iat'] = $this->getTime();
  77.         }
  78.         
  79.                 $base64header = $this->base64UrlEncode(json_encode($this->header, JSON_UNESCAPED_UNICODE));
  80.         $base64payload = $this->base64UrlEncode(json_encode($payload, JSON_UNESCAPED_UNICODE));
  81.         return $base64header . '.' . $base64payload . '.' . $this->signature(
  82.                 $base64header . '.' . $base64payload,
  83.                 $this->key,
  84.                 $this->header['alg']
  85.             );
  86.     }
  87.  
  88.  
  89.     /**
  90.      * 验证token是否有效,默认验证exp,nbf,iat时间
  91.      * @param string $Token 需要验证的token
  92.      * @return bool|string
  93.      */
  94.        
  95.     public function verify(string $Token)
  96.     {
  97.         $tokens = explode('.', $Token);
  98.         if (count($tokens) != 3) {
  99.             return false;
  100.         }
  101.  
  102.         list($base64header, $base64payload, $sign) = $tokens;
  103.  
  104.         //获取jwt算法
  105.         $base64decodeheader = json_decode($this->base64UrlDecode($base64header), true);
  106.         if (empty($base64decodeheader['alg'])) {
  107.             return false;
  108.         }
  109.  
  110.         //签名验证
  111.         if ($this->signature($base64header . '.' . $base64payload, $this->key, $base64decodeheader['alg']) !== $sign) {
  112.             return false;
  113.         }
  114.  
  115.         $this->payload = json_decode($this->base64UrlDecode($base64payload), true);
  116.  
  117.         //签发时间大于当前服务器时间验证失败
  118.         if (isset($this->payload['iat']) && $this->payload['iat'] > $this->time) {
  119.             return false;
  120.         }
  121.  
  122.         //过期时间小宇当前服务器时间验证失败
  123.         if (isset($this->payload['exp']) && $this->payload['exp'] < $this->time) {
  124.             return false;
  125.         }
  126.  
  127.         //该nbf时间之前不接收处理该Token
  128.         if (isset($this->payload['nbf']) && $this->payload['nbf'] > $this->time) {
  129.             return false;
  130.         }
  131.  
  132.         return true;
  133.     }
  134.  
  135.         public function payload(): array
  136.         {
  137.                 return $this->payload;
  138.         }
  139.  
  140.     /**
  141.      * base64UrlEncode  https://jwt.io/ 中base64UrlEncode编码实现
  142.      * @param string $input 需要编码的字符串
  143.      * @return string
  144.      */
  145.     private function base64UrlEncode(string $input)
  146.     {
  147.         return str_replace('=', '', strtr(base64_encode($input), '+/', '-_'));
  148.     }
  149.  
  150.     /**
  151.      * base64UrlEncode https://jwt.io/ 中base64UrlEncode解码实现
  152.      * @param string $input 需要解码的字符串
  153.      * @return bool|string
  154.      */
  155.     private static function base64UrlDecode(string $input)
  156.     {
  157.         $remainder = strlen($input) % 4;
  158.         if ($remainder) {
  159.             $addlen = 4 - $remainder;
  160.             $input .= str_repeat('=', $addlen);
  161.         }
  162.         return base64_decode(strtr($input, '-_', '+/'));
  163.     }
  164.  
  165.     /**
  166.      * HMACSHA256签名  https://jwt.io/ 中HMACSHA256签名实现
  167.      * @param string $input 为base64UrlEncode(header).".".base64UrlEncode(payload)
  168.      * @param string $key
  169.      * @param string $alg 算法方式
  170.      * @return mixed
  171.      */
  172.     private function signature(string $input, string $key, string $alg = 'HS256')
  173.     {
  174.         $alg_config = array(
  175.             'HS256' => 'sha256'
  176.         );
  177.         return $this->base64UrlEncode(hash_hmac($alg_config[$alg], $input, $key, true));
  178.     }
  179. }
  180.  
  181. //example
  182. $data = [
  183.     'name'=>'long',
  184.     'age'=>18,
  185.         'exp' => time() + 60,
  186.        
  187. ];
  188. $jwt = new Jwt;
  189. $token = $jwt->generate($data);
  190.  
  191. if($jwt->verify($token) === true) {
  192.     var_dump($token);
  193.     var_dump($jwt->payload());
  194. }