php使用JWT生成Token

一 . JWT 即 Json Web Token。
隨著技術(shù)的發(fā)展,分布式web應(yīng)用的普及,通過session管理用戶登錄狀態(tài)成本越來越高,因此慢慢發(fā)展成為token的方式做登錄身份校驗,然后通過token去取redis中的緩存的用戶信息,隨著之后jwt的出現(xiàn),校驗方式更加簡單便捷化,無需通過redis緩存,而是直接根據(jù)token取出保存的用戶信息,以及對token可用性校驗,單點登錄更為簡單。

jwt 主要由消息頭header 和 數(shù)據(jù)載體組成。消息頭 header是由6個 標(biāo)準(zhǔn)消息體 key=>value 鍵值對組成,其中key是固定的不能更改,用戶可根據(jù)自己的實際情況選擇需要的部分 header。消息載體 payload [key=>value]數(shù)組,完全是由用戶自定義。

[
   "iss" => "http://example.org", // jwt簽發(fā)者
   "sub" => "1234567890", // jwt所面向的用戶
   "aud"=>"",// 接收jwt的一方
   "exp"=>$time+10,//: jwt的過期時間,這個過期時間必須要大于簽發(fā)時間
   "nbf"=>$time, //: 定義在什么時間之前,該jwt都是不可用的.
   "iat"=>$time, //: jwt的簽發(fā)時間
   "jti"=>"",//: jwt的唯一身份標(biāo)識,主要用來作為一次性token,從而回避重放攻擊。
     // 消息載體
    "data"=>[
         "userid"=>12,
         "isBoss"=>1,
         . . . . . . 
    ],
]
在本人實際開發(fā)中, 用的比較多的是 iat, exp 兩個消息頭。

二 . php生成jwt
php生成jwt可以有兩種途徑 composer庫 lcobucci/jwt & pecl庫cdoco/php-jwt最新版1.0.0

pecl cdoco/php-jwt 擴展的使用:
打開 https://github.com/cdoco/php-jwt 如果你的php 版本是5 ,可選擇當(dāng)前主分支 0.2.5 。如果你是 php7,請切換到分支v1.0.0 (https://github.com/cdoco/php-jwt/tree/v1.0.0) 下載安裝。
下面以安裝 php7版本的 jwt v1.0.0 版本和基本使用案例

# 安裝
$ cd ~/php-extension
$ wget  https://github.com/cdoco/php-jwt/archive/v1.0.0.zip
$ unzip v1.0.1.zip #得到 php-jwt-1.0.0/
$ cd php-jwt-1.0.0/
$ vi php_jwt.h # 修改該文件的版本號,可忽略 (個人習(xí)慣會修改一下) 
找到 #define PHP_JWT_VERSION 配置項 將后面的值 改成 "1.0.0" 然后保存退出
$ /usr/local/php/bin/phpize
$ ./configure --with-php-config=/usr/local/php/bin/php-config
$ make && make install  # 根據(jù)結(jié)果提示查看是否安裝完成
$ vi php.ini # 在追后追加 extension = jwt.so 保存退出
$ php --ri jwt # 查看 擴展版本號是否為 1.0.0

# 使用
$key = "Your custom encrypt key";
$time = time();
$payload = array(
    "data" => [
        "name" => "ZiHang Gao",
        "admin" => true
    ],
    //"iss" => "http://example.org", // jwt簽發(fā)者
    //"sub" => "1234567890", // jwt所面向的用戶
    //"aud"=>"",// 接收jwt的一方
    "exp"=>$time+10,//: jwt的過期時間,這個過期時間必須要大于簽發(fā)時間
    //"nbf"=>$time, //: 定義在什么時間之前,該jwt都是不可用的.
    "iat"=>$time, //: jwt的簽發(fā)時間
    //"jti"=>"",//: jwt的唯一身份標(biāo)識,主要用來作為一次性token,從而回避重放攻擊。
);

// 生成 jwt token
$token = \Cdoco\JWT::encode($payload, $key);
// ...... end
try{
    // 解析你的 jwt token
    $data = \Cdoco\JWT::decode($token, $key);
    var_dump($data);
}catch (Exception $e){
    get_class($e) == "SignatureInvalidException"; // 表示 token 被串改或 加密的 key 被串改
    get_class($e) == "ExpiredSignatureException"; // 表示 token 過期
    get_class($e) == "BeforeValidException"; // 表示 token 在規(guī)定之前的時間內(nèi)不允許使用
    var_dump(get_class($e));
    var_dump($e->getMessage());
}

composer lcobucci/jwt的基本使用

安裝: composer require lcobucci/jwt

/**
 * 生成 jwt
 * @param array $data 消息載體
 * @param int $expire 過期有效時間
 * @param string $secertKey 加密key
 * @return string jwtToken
 */
function generateJwt(array $data,string $secertKey="", int $expire=0):string {
        $signer = new Sha256();
        $currentTime = time();
        $secert = $secert ? : "Your custom encrypt key"; 
        $builder = new Builder();
        if ($expire){
            $builder->expiresAt($currentTime + $expire); //添加過期時間,無過期時間表示永遠有效
        }
        $token = $builder
            ->canOnlyBeUsedAfter($currentTime) //多少秒前該token無法使用
            ->withClaim("data", $data) //設(shè)置數(shù)據(jù)
            ->getToken($signer, new Key($secert));
        $token = strval($token);
        return (string)$token;
    }

 /**
  * 解析你的 jwt token
  * @param string $token 你要解析的 jwtToken 字符串
  * @param string $secret 你的加密 key ,必須與生成token的加密key一致
  * @return array 原jwt的header和payload組成的數(shù)組
  */
function parseJwt(string $token,string $secert=""):array{
        $secert = $secert ? : "Your custom encrypt key";
        $signer = new Sha256();
        try{
            $token = (new Parser())->parse($token);
            if ($token->verify($signer, $secert)) { //驗證token是否被串改或加密的key錯誤
                $validation = new ValidationData();
                $data = (array)$token->getClaim("data"); // 得到消息載體
                if(empty($data)){
                   throw new Exception("empty data"); // 該情況,表示擁護在生成 jwt的時候,沒有放入載體。
                    // 該情況一般不會發(fā)生,
                }
                if(!$token->validate($validation)) {
                    throw new Exception("expire"); // 拋出 token過期的異常
                }
            }else{
                throw new Exception("failed"); // 拋出 token是被串改或加密的key錯誤的異常
            }

        }catch (\Exception $exception){
            // 當(dāng) jwt 解析異常的時候,會出現(xiàn)異常,例如Token過期, secret錯誤等等
            throw new Exception($exception->getMessage(),403);
        }
        return $data;
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容