<thead id="rrjt3"></thead>
      <progress id="rrjt3"><dfn id="rrjt3"></dfn></progress>

      <em id="rrjt3"></em>

        <address id="rrjt3"><ins id="rrjt3"><dfn id="rrjt3"></dfn></ins></address>
          <i id="rrjt3"></i>

        結合PHP TP6 實現 jwt 登陸驗證實例

        時間:2021-08-21 16:31:12 類型:PHP
        字號:    

        JWT優勢與不足, 這里就再細說了, 大家可以登陸某度, 實勁搜, 有存在, 必然有價值, 這里就結合tp6及html前端來個實例, 當然, 現在前端比較流行vue, 其實道理是一樣的, 用vue的話, 你只要把 token 永久保存即可, 比如通過localStorage或者vuex等

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

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

        <?php 
        /**
         * PHP實現jwt
         */
        class Jwt {
        
            //頭部
            private static $header=array(
                'alg'=>'HS256', //生成signature的算法
                'typ'=>'JWT'    //類型
            );
        
            //使用HMAC生成信息摘要時所使用的密鑰
            private static $key='asdf_wr@#&(*@#$&#(@_@#)$#@$_!23kasdf';
        
        
            /**
             * 獲取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(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;
                }
            }
        
        
            /**
             * 驗證token是否有效,默認驗證exp,nbf,iat時間
             * @param string $Token 需要驗證的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"=>"算法錯誤"];
        
                //簽名驗證
                if (self::signature($base64header . '.' . $base64payload, self::$key, $base64decodeheader['alg']) !== $sign)
                    return ["code"=>3,"mes"=>"簽名錯誤"];
        
                $payload = json_decode(self::base64UrlDecode($base64payload), JSON_OBJECT_AS_ARRAY);
        
                //簽發時間大于當前服務器時間驗證失敗
                if (isset($payload['iat']) && $payload['iat'] > time())
                    return ["code"=>4,"mes"=>"簽發時間不對"];
        
                //過期時間小于當前服務器時間驗證失敗
                if (isset($payload['exp']) && $payload['exp'] < time())
                    return ["code"=>5,"mes"=>"已經過期"];
        
                //該nbf時間之前不接收處理該Token
                if (isset($payload['nbf']) && $payload['nbf'] > time())
                    return ["code"=>6,"mes"=>"非處理token時間"];
        
                return ["code"=>1, "payload"=>$payload];
            }
        
        
        
        
            /**
             * base64UrlEncode   https://jwt.io/  中base64UrlEncode編碼實現
             * @param string $input 需要編碼的字符串
             * @return string
             */
            private static function base64UrlEncode(string $input)
            {
                return str_replace('=', '', strtr(base64_encode($input), '+/', '-_'));
            }
        
            /**
             * base64UrlEncode  https://jwt.io/  中base64UrlEncode解碼實現
             * @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簽名實現
             * @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

           訪問登陸頁面:

        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在客戶端存儲起來, 服務器端不存儲任何信息
        			         			//好處: 多點登錄非常方便(服務器段不用每個服務器, 每個站點都存儲用戶信息)
        			         			//壞處: 一經簽發, 在到期之前就會始終有效,除非服務器部署額外的邏輯
        			         		}
        			          }, "json");
        		 	  	    })
        	 	  	 
        	 	  })
        	 </script>

        登陸檢查及生成token

         public function loginCheck(){
                $post = $this->request->post();
                //模擬比較, 實際應用中通常 從數據庫中查詢比對
                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]);
                }
            }

          驗證是否登陸或者過期視圖:

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

        對token進行驗證

         public function jwtverify(){
                if(!$this->request->post("token")){
                     return View::fetch();
                }
                else{
                    //對token進行驗證簽名
                    $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(){
                //在請求頭時接收方法
                return $this->request->header("Authorization");
               
            }

        注意: 默認沒有Authoriztaion信息, 修改下.htaccess文件

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


        黄网站免费 <