日韩精品欧美激情国产一区_中文无码精品一区二区三区在线_岛国毛片AV在线无码不卡_亞洲歐美日韓精品在線_使劲操好爽好粗视频在线播放_日韩一区欧美二区_八戒八戒网影院在线观看神马_亚洲怡红院在线色网_av无码不卡亚洲电影_国产麻豆媒体MDX

結(jié)合PHP TP6 實(shí)現(xiàn) jwt 登陸驗(yàn)證實(shí)例

時(shí)間:2021-08-21 16:31:12 類型:PHP
字號(hào):    

JWT優(yōu)勢(shì)與不足, 這里就再細(xì)說了, 大家可以登陸某度, 實(shí)勁搜, 有存在, 必然有價(jià)值, 這里就結(jié)合tp6及html前端來個(gè)實(shí)例, 當(dāng)然, 現(xiàn)在前端比較流行vue, 其實(shí)道理是一樣的, 用vue的話, 你只要把 token 永久保存即可, 比如通過localStorage或者vuex等

廢話不多說了, 直接上代碼了

1, JWT類文件Jwt.php, 我把它放在extend目錄下, 方便 調(diào)用 

<?php 
/**
 * PHP實(shí)現(xiàn)jwt
 */
class Jwt {

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

    //使用HMAC生成信息摘要時(shí)所使用的密鑰
    private static $key='asdf_wr@#&(*@#$&#(@_@#)$#@$_!23kasdf';


    /**
     * 獲取jwt token
     * @param array $payload jwt載荷   格式如下非必須
     * [
     *  'iss'=>'jwt_admin',  //該JWT的簽發(fā)者
     *  'iat'=>time(),  //簽發(fā)時(shí)間
     *  'exp'=>time()+7200,  //過期時(shí)間
     *  'nbf'=>time()+60,  //該時(shí)間之前不接收處理該Token
     *  'sub'=>'www.admin.com',  //面向的用戶
     *  'jti'=>md5(uniqid('JWT').time())  //該Token唯一標(biāo)識(shí)
     * ]
     * @return bool|string
     */
    public static function getToken(array $payload)
    {
        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,self::$key,self::$header['alg']);
            return $token;
        }else{
            return false;
        }
    }


    /**
     * 驗(yàn)證token是否有效,默認(rèn)驗(yàn)證exp,nbf,iat時(shí)間
     * @param string $Token 需要驗(yàn)證的token
     * @return bool|string
     */
    public static function verifyToken(string $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 ["code"=>2, "mes"=>"算法錯(cuò)誤"];

        //簽名驗(yàn)證
        if (self::signature($base64header . '.' . $base64payload, self::$key, $base64decodeheader['alg']) !== $sign)
            return ["code"=>3,"mes"=>"簽名錯(cuò)誤"];

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

        //簽發(fā)時(shí)間大于當(dāng)前服務(wù)器時(shí)間驗(yàn)證失敗
        if (isset($payload['iat']) && $payload['iat'] > time())
            return ["code"=>4,"mes"=>"簽發(fā)時(shí)間不對(duì)"];

        //過期時(shí)間小于當(dāng)前服務(wù)器時(shí)間驗(yàn)證失敗
        if (isset($payload['exp']) && $payload['exp'] < time())
            return ["code"=>5,"mes"=>"已經(jīng)過期"];

        //該nbf時(shí)間之前不接收處理該Token
        if (isset($payload['nbf']) && $payload['nbf'] > time())
            return ["code"=>6,"mes"=>"非處理token時(shí)間"];

        return ["code"=>1, "payload"=>$payload];
    }




    /**
     * base64UrlEncode   https://jwt.io/  中base64UrlEncode編碼實(shí)現(xiàn)
     * @param string $input 需要編碼的字符串
     * @return string
     */
    private static function base64UrlEncode(string $input)
    {
        return str_replace('=', '', strtr(base64_encode($input), '+/', '-_'));
    }

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

    /**
     * HMACSHA256簽名   https://jwt.io/  中HMACSHA256簽名實(shí)現(xiàn)
     * @param string $input 為base64UrlEncode(header).".".base64UrlEncode(payload)
     * @param string $key
     * @param string $alg   算法方式
     * @return mixed
     */
    private static function signature(string $input, string $key, string $alg = 'HS256')
    {
        $alg_config=array(
            'HS256'=>'sha256'
        );
        return self::base64UrlEncode(hash_hmac($alg_config[$alg], $input, $key,true));
    }
}
 ?>

  建立登陸控制器JwtController.php

   訪問登陸頁(yè)面:

public function loginTest(){
        return View::fetch('login');
    }

   登陸視圖:

 <form style="width: 300px; margin: 0 auto;">
		  <li>
			   <input type="text" name="username" placeholder="用戶名">
		  </li>
		  <li>
			   <input type="password" name="userpwd" placeholder="用戶密碼">
		  </li>
		  <li>
			   <input type="button" value="登陸" id="login">
		  </li>
	 </form>
	 <script type="text/javascript">
	 	  $(function(){
	 	  	  $("#login").on("click", function(){
	 	  	  	     let username = $("input[name='username']").val();
		 	  	     let userpwd  = $("input[name='userpwd']").val();
		 	  	     $.post("/jwt/loginCheck", { "username": username,"userpwd" : userpwd },function(data){
			         		if(data.code == 1){
			         			localStorage.setItem("token",data.token);
			         			//將token在客戶端存儲(chǔ)起來, 服務(wù)器端不存儲(chǔ)任何信息
			         			//好處: 多點(diǎn)登錄非常方便(服務(wù)器段不用每個(gè)服務(wù)器, 每個(gè)站點(diǎn)都存儲(chǔ)用戶信息)
			         			//壞處: 一經(jīng)簽發(fā), 在到期之前就會(huì)始終有效,除非服務(wù)器部署額外的邏輯
			         		}
			          }, "json");
		 	  	    })
	 	  	 
	 	  })
	 </script>

登陸檢查及生成token

 public function loginCheck(){
        $post = $this->request->post();
        //模擬比較, 實(shí)際應(yīng)用中通常 從數(shù)據(jù)庫(kù)中查詢比對(duì)
        if($post["username"] == "admin" && $post["userpwd"] == "123456"){
             $payload=[
                'iss'=>'莊子',
                'iat'=>time(),
                'exp'=>time()+7200,
                'nbf'=>time(),
                'sub'=>'用戶登陸操作',
                'jti'=>md5(uniqid('JWT').time()),
                "username"=>$post["username"]
            ];
            $token=\Jwt::getToken($payload);
            return json(["code"=>1, "mes"=>"登陸成功","token"=>$token]);
        }
    }

  驗(yàn)證是否登陸或者過期視圖:

$(function(){
	 	  	         if(localStorage.getItem("token") != ""){
	 	  	         	 $.post("/jwt/jwtverify", 
	 	  	         	 		{ "token": localStorage.getItem("token")},
	 	  	         	 	   	function(data){
	 	  	         	 	   		if(data.code == 1){
	 	  	         	 	   			console.log("驗(yàn)證成功");
	 	  	         	 	   		}
	 	  	         	 	   		else{
	 	  	         	 	   			console.log("驗(yàn)證失敗  ");
	 	  	         	 	   		}
	 	  	         	 	   	},
	 	  	         	 	    "json");
	 	  	         }
	 	  	         //或者通過 在 HTTP 請(qǐng)求的頭信息Authorization字段里面 如下
			         /* if(localStorage.getItem("token") != ""){
	 	  	         	 $.ajax({
	 	  	         	 	 "url" : "/jwt/jwtverify1",
	 	  	         	 	 "dataType":"json",
	 	  	         	 	 success:function(data){
	 	  	         	 	 	if(data.code == 1){
	 	  	         	 	   			console.log("驗(yàn)證成功");
	 	  	         	 	   		}
	 	  	         	 	   		else{
	 	  	         	 	   			console.log("驗(yàn)證失敗  ");
	 	  	         	 	   		}
	 	  	         	 	 },
	 	  	         	 	 beforeSend : function(request) {
								request.setRequestHeader("Authorization", localStorage.getItem("token"));
							},
	 	  	         	 })
	 	  	         }
	 	  	         */
	 	  	         //tp服務(wù)端接收方法 : $this->request->header("Authorization");
	 	  	 
	 	  })

對(duì)token進(jìn)行驗(yàn)證

 public function jwtverify(){
        if(!$this->request->post("token")){
             return View::fetch();
        }
        else{
            //對(duì)token進(jìn)行驗(yàn)證簽名
            $result = \Jwt::verifyToken($this->request->post("token"));
            if($result["code"] == 1){
                return json(["code"=>1,"mes"=>"success", "username"=>$result["payload"]["username"]]);
            }
            else{
                return json(["code"=>2,"mes"=>"fail"]);
            }
        }
       
    }
    public function jwtverify1(){
        //在請(qǐng)求頭時(shí)接收方法
        return $this->request->header("Authorization");
       
    }

注意: 默認(rèn)沒有Authoriztaion信息, 修改下.htaccess文件

 Options +FollowSymlinks -Multiviews
  RewriteEngine On

  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteRule ^(.*)$ index.php?/$1 [QSA,PT,L]
   #增加如下內(nèi)容
  SetEnvIf Authorization .+ HTTP_AUTHORIZATION=$0


<