jwt鑒權學習 (php示例代碼)


  前段時間聽朋友講起 jwt鑒權,博主我是一臉懵逼,通過朋友堅持不懈的講解,我終於聽懂了,jwt就是登陸token校驗嘛

  然而事情並不是博主想象的那么簡單,在一個艷陽高照,晴空萬里的夜晚,博主手賤百度了一波jwt,才發現問題所在之處

  首先:我的登錄token校驗邏輯

      用戶輸入賬號密碼登錄,賬號密碼校驗正確,生成一個隨機拼接的token,返回給前端,並存儲到數據庫中,然后根據前端發送的token和數據庫的token對比,從而達到校驗效果

      (缺點,token永不過期,如果設置了定時清空所有token,用戶體驗極差)

  百度上大佬們的博客講解jwt鑒權的校驗邏輯

      用戶輸入賬號密碼登錄,賬號密碼校驗正確,使用n個數據(詳情看后面的代碼)組成的數組,進行加密生成字符串,拼接上加密算法名稱類型加密的字符串,自己設置

    的秘鑰加前面兩個數據再進行加密拼接,於是乎就組成了一個token,並返回,服務端並不存儲任何數據   

      生成token的示例 :  aaa.bbb.ccc        (加密后的數據a+ . +加密后的數據b+ . +(加密(加密前的數據a+加密前的數據b+秘鑰)))

      當用戶用token發起請求的時候,服務端則會拿到token,解密再進行校驗,token的有效時間是否過期什么的

 下面附上代碼:

   

<?php
/**
 * PHP實現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',  //請求生成token的用戶
     *  'iat'=>time(),  //生成時間
     *  'exp'=>time()+7200,  //過期時間
     *  'nbf'=>time()+60,  //生成token  60秒后方可使用
     *  'sub'=>'www.admin.com',  //服務端網址
     *  'jti'=>md5(uniqid('JWT').time())  //該Token唯一標識
     * ]
     * @return bool|string
     */
    public static function getToken($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($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));
    }
}





    //例子一
    //生成token
    $payload=array('sub'=>'1234567890','name'=>'John Doe','iat'=>1516239022);
    $jwt=new Jwt;
    $token=$jwt->getToken($payload);
    echo "<pre>";
    echo $token;
    //生成的token
    // eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.keH6T3x1z7mmhKL1T3r9sQdAxxdzB6siemGMr_6ZOwU

    //校驗token
    $getPayload=$jwt->verifyToken($token);
    echo "<br><br>";
    var_dump($getPayload);
    echo "<br><br>";
    //解密后的返回值
    //    array(3) {
    //        ["sub"]=>
    //      string(10) "1234567890"
    //        ["name"]=>
    //      string(8) "John Doe"
    //        ["iat"]=>
    //      int(1516239022)
    //    }






    //例子二
    //生成token
    $payload_test=array('iss'=>'admin','iat'=>time(),'exp'=>time()+7200,'nbf'=>time(),'sub'=>'www.admin.com','jti'=>md5(uniqid('JWT').time()));;
    $token_test=Jwt::getToken($payload_test);
    echo "<pre>";
    echo $token_test;
    //  生成的token值
    //  eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTU4Mzk4MTc2NywiZXhwIjoxNTgzOTg4OTY3LCJuYmYiOjE1ODM5ODE3NjcsInN1YiI6Ind3dy5hZG1pbi5jb20iLCJqdGkiOiJhMzdiOTRlZTc5YzE2ZDI2YTA1NWY3OGI2Mzg0M2YwOSJ9.RyHdg5lTsnquY0G_q053DtR5FnSbBrU_GdY_j3GPLcs


    //校驗token
    $getPayload_test=Jwt::verifyToken($token_test);
    echo "<br><br>";
    var_dump($getPayload_test);
    echo "<br><br>";
    //解密后的返回值
    //    array(6) {
    //        ["iss"]=>
    //      string(5) "admin"
    //        ["iat"]=>
    //      int(1583981767)
    //      ["exp"]=>
    //      int(1583988967)
    //      ["nbf"]=>
    //      int(1583981767)
    //      ["sub"]=>
    //      string(13) "www.admin.com"
    //        ["jti"]=>
    //      string(32) "a37b94ee79c16d26a055f78b63843f09"
    //    }

 

 

原文地址:https://blog.csdn.net/qq_33858250/article/details/89419869


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM