深入淺出:JWT(JSON Web Token)鑑權

本文索引:

  • 第一部分 基本概念
  • 第二部分 使用流程
  • 第三部分 實現代碼
深入淺出:JWT(JSON Web Token)鑑權

第一部分 基本概念

JWT就是一個字符串,經過加密處理與校驗處理的字符串,由三個部分組成。基於token的身份驗證可以替代傳統的cookie+session身份驗證方法。三個部分分別如下:

<code> header.payload.signature/<code>

header部分:

<code>{"typ":"JWT","alg":"HS256"}/<code>

這就是一個json串,兩個字段都是必須的,alg字段指定了生成signature的算法,默認值為 HS256,可以自己指定其他的加密算法,如RSA.經過base64encode就可以得到 header.
payload部分:

<code>$payload=[            'iss' => $issuer, //簽發者            'iat' => $_SERVER['REQUEST_TIME'], //什麼時候簽發的            'exp' => $_SERVER['REQUEST_TIME'] + 7200 //過期時間            'uid'=>1111        ];/<code>

signature部分
將 header和 payload使用header中指定的加密算法加密,當然加密過程還需要自定秘鑰,自己選一個字符串就可以了。

<code>HMACSHA256(  base64UrlEncode(header) + "." +  base64UrlEncode(payload),  secret)/<code>

php實現代碼:

<code> 
'JWT', 'alg' => $alg])) . '.' . self::urlsafeB64Encode(json_encode($payload)); return $jwt . '.' . self::signature($jwt, $key, $alg); } public static function signature(string $input, string $key, string $alg) { return hash_hmac($alg, $input, $key); }/<code>

將以上三個部分連起來就是JWT了。

參數解釋

深入淺出:JWT(JSON Web Token)鑑權

Screen-Shot-2018-09-06-at-3.24.30-PM.png


第二部分 JWT使用流程


深入淺出:JWT(JSON Web Token)鑑權

JWT使用流程


實現步驟:

  • 用戶登錄:輸入用戶名和密碼
  • 服務器進行用戶名和密碼的校驗,通過之後生成JWT返回給前端
  • 每次用戶請求API的時候都帶上JWT
  • 服務端收到JWT做校驗

第三部分 實現代碼

首先composer安裝一個JWT庫,這裡使用的是firebase的庫,

<code>composer require firebase/php-jwt/<code>

服務端在生成token時,加入少量的用戶信息,比如用戶的id。服務端接收到token之後,可以解析出這些數據,從而將token和用戶關聯了起來。

使用很簡單,傳入秘鑰,生成Token:

<code>private function generateToken($key){        vendor('JWT.JWT');        $key = $user_key;        $token = array(            "iss" => "https://feifei50.com", // Issued At Claim            "aud" => "https://feifei50.com", // Audience Claim            "iat" => $_SERVER['REQUEST_TIME'], // Issued At Claim            "nbf" => $_SERVER['REQUEST_TIME']-300, // Not Before Claim            "exp" => $_SERVER["REQUEST_TIME"]+3600 // Expire Time Claim        );        $jwt = JWT::encode($token, $key);        return $jwt;    }/<code>

返回的$jwt大概是這個樣子:

<code>//eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczpcL1wvZmVpZmVpNTAuY29tIiwiYXVkIjoiaHR0cHM6XC9cL2ZlaWZlaTUwLmNvbSIsImlhdCI6MTUzNjI2OTM4NSwibmJmIjoxNTM2MjYxMDY1LCJleHAiOjE1MzYyNzk1NjV9.W19LwKH2eQbYs6YHKkbk7bOQK2dBfmV8jcNGIN4OGlY/<code>

key就是用來混淆的,自己隨便定義好了,encode 需要key,decode 也需要key,這裡用md5加密一下,會加入一個令牌混淆加密

在前端拿到這個token之後就將這個token放在LocalStroage中,每發送AJAX請求的時候都帶上這個token給服務端,服務端解碼這個token來做校驗,如果校驗沒有通過,那麼強制其跳回登錄頁面。

firebase的這個JWT會在解碼的時候做部分的校驗,比如key是否正確,token是否expired之類的,具體參考源碼,很容易理解。以後後端每次拿到這組Token就要從Token中進行解碼:

解碼Token

<code>private function decodeToken($jwt,$user_key){    JWT::$leeway = 300; // $leeway in seconds    $decoded = JWT::decode($jwt, $user_key, array('HS256'));    return $decoded;}/<code>

這樣解碼之後就拿到了之前定義的payload的信息即說需要的用戶信息。


本文作者熊冰,個人網站[Bing的天涯路],轉載請註明出處。


分享到:


相關文章: