分享按钮

JWT(JSON Web Tokens)使用

默认分类 / 2749人浏览 / 0人评论

thinkphp + JWT

   1,composer安装jwt(测试使用的3.2)     

composer require lcobucci/jwt  3.2

   2.封装的代码

/**
* Created by PhpStorm.
* User: asus
* Date: 2021/3/15
* Time: 21:58
*/

namespace app\common\controller;
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\ValidationData;


/**
* 单例一次请求中所有出现使用jwt的地方都是一个用户
*
* */

class JwtAuth
{
   protected $token=null;

   protected  $iss='http://imagechuli.com';

   protected $aud='xing_app';

   protected  $uid;

   protected $secrect='sdgfdjhasfsdhggj235657###%';

   /**
    * decode token
    * */
   protected $decodeToken;

   /**
   单例模式 jwtauth句柄
    */
   protected  static $instance=null;

   /**
    *
    * 获取 jwtauth的句柄
    */

   public static  function getInstance(){
       if(is_null(self::$instance)){
           self::$instance= new self();
       }
       return self::$instance;
   }
   /**
    * 私有化构造函数
    *
    * */
   protected function __construct()
   {

   }

   protected function __clone()
   {
       // TODO: Implement __clone() method.
   }

   /**
    * 获取token
    * */
   public function getToken(){
       return (string)$this->token;
   }

   /**
    * 设置token
    * */
   public function setToken($token){
       $this->token=$token;
   }

   /**
    *
    */

   public function setUid($uid){
       $this->uid=$uid;
       return $this;
   }


   /**
    *
    * 编码 jwt token
    **/

   public function encode(){
       $time=time();
       $this->token =(new  Builder())->setHeader('alg','HS256')
           ->setIssuer( $this->iss) //配置发行者(iss声明)
           -> setAudience($this->aud) //配置听众(音频声明)
           -> setIssuedAt($time) //配置发布令牌的时间(iat声明)
           -> setExpiration($time+3600)//配置令牌的过期时间(exp声明)
           -> set('uid',$this->uid)//配置一个新的声明,称为“ uid”
           ->sign(new Sha256(),$this->secrect)
           -> getToken(); //检索生成的令牌
       return $this;
   }

   /**
    *
    *
    */

   public function decode(){
       if(!$this->decodeToken){
           $this->decodeToken= (new Parser())->parse((string)$this->token);
           $this->uid=$this->decodeToken->getClaim('uid');
       }
       return $this->decodeToken;

   }

   /**verify  token
    *
    * */
   public function verify(){
       $result=$this->decode()->verify(new Sha256(),$this->secrect);
       return $result;
   }

   /**
    *validate
    * */
   public function validate(){

       $data=new ValidationData();

       $data->setIssuer($this->iss);
       $data->setAudience($this->aud);

       return $this->decode()->validate($data);


   }

}

3.生成 token 

$jwtauth= JwtAuth::getInstance();

$token=$jwtauth->setUid(1)->encode()->getToken();

4,解密 token

$token=$this->request->param('token');
if(!$token){
   $this->error('参数错误');
}
$jwt=JwtAuth::getInstance();
$jwt->setToken($token);

if(!$jwt->verify()  || !$jwt->validate()){
   $this->error('返回失败');
}else{
   $data= $jwt->decode()->getClaim('uid');

}


2)不使用composer安装jwt 

class Jwt {

   //头部
   private static $header=array(
       'alg'=>'HS256', //生成signature的算法
       'typ'=>'JWT'    //类型
   );

   //使用HMAC生成信息摘要时所使用的密钥
   private static $key='123456';


   /**
    * 获取jwt token
    * @param array $payload jwt载荷   格式如下非必须
    * [
    *  'iss'=>'jwt_admin',  //该JWT的签发者
    *  'iat'=>time(),  //签发时间
    *  'exp'=>time()+7200,  //过期时间
    *  'nbf'=>time()+60,  //该时间之前不接收处理该Token
    *  'sub'=>'www.admin.com',  //面向的用户
    *  'jti'=>md5(uniqid('JWT').time())  //该Token唯一标识
    * ]
    * @return bool|string
    */
   public static function getToken($payload,$key)
   {
       if(is_array($payload))
       {
           $base64header=self::base64UrlEncode(json_encode(self::$header,JSON_UNESCAPED_UNICODE));
           $base64payload=self::base64UrlEncode(json_encode($payload,JSON_UNESCAPED_UNICODE));
           $token=$base64header.'.'.$base64payload.'.'.self::signature($base64header.'.'.$base64payload,$key,self::$header['alg']);
           return $token;
       }else{
           return false;
       }
   }


   /**
    * 验证token是否有效,默认验证exp,nbf,iat时间
    * @param string $Token 需要验证的token
    * @return bool|string
    */
   public static function verifyToken($Token)
   {
       $tokens = explode('.', $Token);
       if (count($tokens) != 3)
           return false;

       list($base64header, $base64payload, $sign) = $tokens;

       //获取jwt算法
       $base64decodeheader = json_decode(self::base64UrlDecode($base64header), JSON_OBJECT_AS_ARRAY);
       if (empty($base64decodeheader['alg']))
           return false;

       //签名验证
       if (self::signature($base64header . '.' . $base64payload, self::$key, $base64decodeheader['alg']) !== $sign)
           return false;

       $payload = json_decode(self::base64UrlDecode($base64payload), JSON_OBJECT_AS_ARRAY);

       //签发时间大于当前服务器时间验证失败
       if (isset($payload['iat']) && $payload['iat'] > time())
           return false;

       //过期时间小宇当前服务器时间验证失败
       if (isset($payload['exp']) && $payload['exp'] < time())
           return false;

       //该nbf时间之前不接收处理该Token
       if (isset($payload['nbf']) && $payload['nbf'] > time())
           return false;

       return $payload;
   }




   /**
    * base64UrlEncode   https://jwt.io/  中base64UrlEncode编码实现
    * @param string $input 需要编码的字符串
    * @return string
    */
   private static function base64UrlEncode($input)
   {
       return str_replace('=', '', strtr(base64_encode($input), '+/', '-_'));
   }

   /**
    * base64UrlEncode  https://jwt.io/  中base64UrlEncode解码实现
    * @param string $input 需要解码的字符串
    * @return bool|string
    */
   private static function base64UrlDecode($input)
   {
       $remainder = strlen($input) % 4;
       if ($remainder) {
           $addlen = 4 - $remainder;
           $input .= str_repeat('=', $addlen);
       }
       return base64_decode(strtr($input, '-_', '+/'));
   }

   /**
    * HMACSHA256签名   https://jwt.io/  中HMACSHA256签名实现
    * @param string $input 为base64UrlEncode(header).".".base64UrlEncode(payload)
    * @param string $key
    * @param string $alg   算法方式
    * @return mixed
    */
   private static function signature($input, $key, $alg = 'HS256')
   {
       $alg_config=array(
           'HS256'=>'sha256'
       );
       return self::base64UrlEncode(hash_hmac($alg_config[$alg], $input, $key,true));
   }
}







感谢博主,喝杯咖啡~