PHP实现jwt加密解密

PHP实现jwt加密解密

  1. <?php
  2. /**
  3. * Description:
  4. * Author: WangSx
  5. * DateTime: 2020-04-22 14:02
  6. */
  7. namespace App\Library\Encryption;
  8. use App\Common\BaseClasses\CallStaticBase;
  9. /**
  10. * Description: 二维码专用key,生成/验证器
  11. * Author: WangSx
  12. * DateTime: 2020-04-22 14:43
  13. * Class Encryption
  14. * @package App\Library\Encryption
  15. * @method static array makeKey() 获取唯一的token
  16. * @method static array verifyToken(string $Token) 验证token是否有效, 默认验证exp, nbf, iat时间
  17. */
  18. class Encryption extends CallStaticBase
  19. {
  20. private static $header = [
  21. 'alg' => 'HS256', //生成signature的算法
  22. 'typ' => 'JWT' //类型
  23. ];
  24. //使用HMAC生成信息摘要时所使用的密钥
  25. private static $key = 'wangsx';
  26. private static $iss = 'yi_z_p'; // 平台标记
  27. private static $sub = 'yi_z_p_er'; // 面向用户
  28. private static $expire_time = 300; //默认有效期 5分钟
  29. /**
  30. * Description: 获取唯一的token
  31. * Author: WangSx
  32. * DateTime: 2020-04-22 15:27
  33. * @return array [失效期,key]
  34. */
  35. public function _makeKey()
  36. {
  37. $expire_time = time() + self::$expire_time;
  38. $arr = [
  39. 'iss' => self::$iss, //该JWT的签发者
  40. 'iat' => time(), //签发时间
  41. 'exp' => $expire_time, //过期时间
  42. 'nbf' => time() + 1, //该时间之前不接收处理该Token
  43. 'sub' => self::$sub, //面向的用户
  44. 'jti' => md5(uniqid('JWT') . time()) //该Token唯一标识
  45. ];
  46. $key = $this->getToken($arr);
  47. return [
  48. $expire_time,
  49. $key
  50. ];
  51. }
  52. /**
  53. * Description: 获取jwt token
  54. * Author: WangSx
  55. * DateTime: 2020-04-22 14:28
  56. * @param array $payload jwt载荷 格式如下非必须
  57. * [
  58. * 'iss'=>'jwt_admin', //该JWT的签发者
  59. * 'iat'=>time(), //签发时间
  60. * 'exp'=>time()+7200, //过期时间
  61. * 'nbf'=>time()+60, //该时间之前不接收处理该Token
  62. * 'sub'=>'www.admin.com', //面向的用户
  63. * 'jti'=>md5(uniqid('JWT').time()) //该Token唯一标识
  64. * ]
  65. * @return bool|string
  66. */
  67. public function getToken(array $payload)
  68. {
  69. if (is_array($payload)) {
  70. $base64header = self::base64UrlEncode(json_encode(self::$header, JSON_UNESCAPED_UNICODE));
  71. $base64payload = self::base64UrlEncode(json_encode($payload, JSON_UNESCAPED_UNICODE));
  72. $token = $base64header . '.' . $base64payload . '.' . self::signature($base64header . '.' . $base64payload, self::$key, self::$header['alg']);
  73. return $token;
  74. } else {
  75. return false;
  76. }
  77. }
  78. /**
  79. * Description: 验证token是否有效,默认验证exp,nbf,iat时间
  80. * Author: WangSx
  81. * DateTime: 2020-04-22 15:08
  82. * @param string $Token 需要验证的token
  83. * @return array|\Illuminate\Http\JsonResponse|int|string
  84. */
  85. public function _verifyToken(string $Token)
  86. {
  87. $tokens = explode('.', $Token);
  88. if (count($tokens) != 3) {
  89. return failed('非官方平台签发,请重试!');
  90. }
  91. list($base64header, $base64payload, $sign) = $tokens;
  92. //获取jwt算法
  93. $base64decodeheader = json_decode(self::base64UrlDecode($base64header), JSON_OBJECT_AS_ARRAY);
  94. if (empty($base64decodeheader['alg'])) {
  95. return failed('非官方平台签发,请重试!');
  96. }
  97. //签名验证
  98. if (self::signature($base64header . '.' . $base64payload, self::$key, $base64decodeheader['alg']) !== $sign) {
  99. return failed('验签失败!');
  100. }
  101. $payload = json_decode(self::base64UrlDecode($base64payload), JSON_OBJECT_AS_ARRAY);
  102. // 验证是否本平台签发
  103. if (empty($payload['iss']) || empty($payload['sub'])) {
  104. return failed('非官方平台签发,请重试!');
  105. }
  106. if (($payload['iss'] != self::$iss) || ($payload['sub'] != self::$sub)) {
  107. return failed('非官方秘钥,请重试!~');
  108. }
  109. //签发时间大于当前服务器时间验证失败
  110. if (isset($payload['iat']) && $payload['iat'] > time()) {
  111. return failed('非官方签发,请重试!');
  112. }
  113. //过期时间小于当前服务器时间验证失败
  114. if (isset($payload['exp']) && $payload['exp'] < time()) {
  115. return failed('秘钥已经失效,请重试!');
  116. }
  117. //该nbf时间之前不接收处理该Token
  118. if (isset($payload['nbf']) && $payload['nbf'] > time()) {
  119. return failed('不在有效范围内,请重试!');
  120. }
  121. return $payload;
  122. }
  123. /**
  124. * Description: base64UrlEncode https://jwt.io/ 中base64UrlEncode编码实现
  125. * Author: WangSx
  126. * DateTime: 2020-04-22 14:19
  127. * @param string $input
  128. * @return mixed
  129. */
  130. private static function base64UrlEncode(string $input)
  131. {
  132. return str_replace('=', '', strtr(base64_encode($input), '+/', '-_'));
  133. }
  134. /**
  135. * Description: base64UrlEncode https://jwt.io/ 中base64UrlEncode解码实现
  136. * Author: WangSx
  137. * DateTime: 2020-04-22 14:18
  138. * @param string $input 需要解码的字符串
  139. * @return bool|string
  140. */
  141. private static function base64UrlDecode(string $input)
  142. {
  143. $remainder = strlen($input) % 4;
  144. if ($remainder) {
  145. $addlen = 4 - $remainder;
  146. $input .= str_repeat('=', $addlen);
  147. }
  148. return base64_decode(strtr($input, '-_', '+/'));
  149. }
  150. /**
  151. * Description: HMACSHA256签名 https://jwt.io/ 中HMACSHA256签名实现
  152. * Author: WangSx
  153. * DateTime: 2020-04-22 14:20
  154. * @param string $input 为base64UrlEncode(header).".".base64UrlEncode(payload)
  155. * @param string $key
  156. * @param string $alg 算法方式
  157. * @return mixed
  158. */
  159. private static function signature(string $input, string $key, string $alg = 'HS256')
  160. {
  161. $alg_config = array(
  162. 'HS256' => 'sha256'
  163. );
  164. return self::base64UrlEncode(hash_hmac($alg_config[$alg], $input, $key, true));
  165. }
  166. }


评论 0

发表评论

Top