当前位置:首页 > PHP教程 > php高级应用 > 列表

php实现JWT验证的实例教程

发布:smiling 来源: PHP粉丝网  添加日期:2022-04-02 09:55:53 浏览: 评论:0 

JWT,全称 Json web token,是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

php实现JWT,本例使用thinkphp框架,代码如下:

在vendor包中建立Jwt.php,建立类文件

  1. class Jwt { 
  2.    
  3.  //头部 
  4.  private static $header=array
  5.   'alg'=>'HS256'//生成signature的算法 
  6.   'typ'=>'JWT' //类型 
  7.  ); 
  8.    
  9.  //使用HMAC生成信息摘要时所使用的密钥 
  10.  private static $key='123456'
  11.    
  12.    
  13.  /** 
  14.   * 获取jwt token 
  15.   * @param array $payload jwt载荷 格式如下非必须 
  16.   * [ 
  17.   * 'iss'=>'jwt_admin', //该JWT的签发者 
  18.   * 'iat'=>time(), //签发时间 
  19.   * 'exp'=>time()+7200, //过期时间 
  20.   * 'nbf'=>time()+60, //该时间之前不接收处理该Token 
  21.   * 'sub'=>'www.admin.com', //面向的用户 
  22.   * 'jti'=>md5(uniqid('JWT').time()) //该Token唯一标识 
  23.   * ] 
  24.   * @return bool|string 
  25.   */ 
  26.  public static function getToken($payload
  27.  { 
  28.   if(is_array($payload)) 
  29.   { 
  30.    $base64header=self::base64UrlEncode(json_encode(self::$header,JSON_UNESCAPED_UNICODE)); 
  31.    $base64payload=self::base64UrlEncode(json_encode($payload,JSON_UNESCAPED_UNICODE)); 
  32.    $token=$base64header.'.'.$base64payload.'.'.self::signature($base64header.'.'.$base64payload,self::$key,self::$header['alg']); 
  33.    return $token
  34.   }else
  35.    return false; 
  36.   } 
  37.  } 
  38.    
  39.    
  40.  /** 
  41.   * 验证token是否有效,默认验证exp,nbf,iat时间 
  42.   * @param string $Token 需要验证的token 
  43.   * @return bool|string 
  44.   */ 
  45.  public static function verifyToken($Token
  46.  { 
  47.   $tokens = explode('.'$Token); 
  48.   if (count($tokens) != 3) 
  49.    return false; 
  50.    
  51.   list($base64header$base64payload$sign) = $tokens
  52.    
  53.   //获取jwt算法 
  54.   $base64decodeheader = json_decode(self::base64UrlDecode($base64header), JSON_OBJECT_AS_ARRAY); 
  55.   if (emptyempty($base64decodeheader['alg'])) 
  56.    return false; 
  57.    
  58.   //签名验证 
  59.   if (self::signature($base64header . '.' . $base64payload, self::$key$base64decodeheader['alg']) !== $sign
  60.    return false; 
  61.    
  62.   $payload = json_decode(self::base64UrlDecode($base64payload), JSON_OBJECT_AS_ARRAY); 
  63.    
  64.   //签发时间大于当前服务器时间验证失败 
  65.   if (isset($payload['iat']) && $payload['iat'] > time()) 
  66.    return false; 
  67.    
  68.   //过期时间小宇当前服务器时间验证失败 
  69.   if (isset($payload['exp']) && $payload['exp'] < time()) 
  70.    return false; 
  71.    
  72.   //该nbf时间之前不接收处理该Token 
  73.   if (isset($payload['nbf']) && $payload['nbf'] > time()) 
  74.    return false; 
  75.    
  76.   return $payload
  77.  } 
  78.    
  79.    
  80.    
  81.    
  82.  /** 
  83.   * base64UrlEncode https://jwt.io/ 中base64UrlEncode编码实现 
  84.   * @param string $input 需要编码的字符串 
  85.   * @return string 
  86.   */ 
  87.  private static function base64UrlEncode($input
  88.  { 
  89.   return str_replace('='''strtr(base64_encode($input), '+/''-_')); 
  90.  } 
  91.    
  92.  /** 
  93.   * base64UrlEncode https://jwt.io/ 中base64UrlEncode解码实现 
  94.   * @param string $input 需要解码的字符串 
  95.   * @return bool|string 
  96.   */ 
  97.  private static function base64UrlDecode($input
  98.  { 
  99.   $remainder = strlen($input) % 4; 
  100.   if ($remainder) { 
  101.    $addlen = 4 - $remainder
  102.    $input .= str_repeat('='$addlen); 
  103.   } 
  104.   return base64_decode(strtr($input'-_''+/')); 
  105.  } 
  106.    
  107.  /** 
  108.   * HMACSHA256签名 https://jwt.io/ 中HMACSHA256签名实现 
  109.   * @param string $input 为base64UrlEncode(header).".".base64UrlEncode(payload) 
  110.   * @param string $key 
  111.   * @param string $alg 算法方式 
  112.   * @return mixed 
  113.   */ 
  114.  private static function signature($input$key$alg = 'HS256'
  115.  { 
  116.   $alg_config=array
  117.    'HS256'=>'sha256' 
  118.   ); 
  119.   return self::base64UrlEncode(hash_hmac($alg_config[$alg], $input$key,true)); 
  120.  } 

调用JWT验证的方法,代码如下:

1.构建token方法

  1. public function makeToken(){ 
  2.      $uname=$this->uname;    $currtime=time(); 
  3.      if(emptyempty($this->uname)){ echo json_encode(array('code'=>-1,'msg'=>'[主账号]参数为空'),JSON_UNESCAPED_UNICODE);   exit(); }    
  4.      .... 
  5.      //jwt验证 
  6.      vendor("Jwt.Jwt"); 
  7.      $jwt = new \Jwt(); 
  8. //这里构造jwt参数,可以参照jwt规范,各字段可以自行定义内容    $payload=array('iss'=>'xesport','sub'=>'xxx_player','name'=>$playerName,'iat'=>$currtime,'jti'=>md5(uniqid('JWT').$currtime)); 
  9.      $token=$jwt->getToken($payload); $this->token=$token
  10.      $url='http://xxx?token='.$token
  11.      $data=array('url'=>$url); 
  12.        
  13.      echo json_encode(array('code'=>1,'data'=>$data,),JSON_UNESCAPED_UNICODE); exit(); 
  14.    
  15.     } 

2.验证token的方法

  1. //验证token 
  2. public function verifyToken(){ 
  3.      $token=$_REQUEST['token']; 
  4.      if(emptyempty($token)){ echo json_encode(array('code'=>-1,'msg'=>'[token]参数为空!'),JSON_UNESCAPED_UNICODE); exit(); } 
  5.   vendor("Jwt.Jwt"); 
  6.      $jwt = new \Jwt();   
  7.      $res_token=$jwt->verifyToken($token); 
  8.   //var_dump('res_token==',$res_token); 
  9.      if(emptyempty($res_token)){ echo json_encode(array('code'=>-2,'msg'=>'[token]验证失败!'),JSON_UNESCAPED_UNICODE); exit(); } 
  10.      $playerName=$res_token['name']; 
  11.      //echo $playerName; die; 
  12.      这里可以写从数据库查询验证user是否存在,返回 $userInfo 
  13.      if(emptyempty($userInfo)){ echo json_encode(array('code'=>-3,'msg'=>'[token]验证用户无效!'),JSON_UNESCAPED_UNICODE);    exit(); } 
  14.      $data=array('username'=>$playerName); 
  15.      echo json_encode(array('code'=>1,'data'=>$data,'msg'=>'[token]验证成功'),JSON_UNESCAPED_UNICODE); exit(); 
  16.     } 

这样,我们通过控制器方法调用该方法,传递参数token,就可以解析token中包含的认证凭据信息,从而做后续业务处理逻辑。

Tags: JWT验证实例

分享到: