當前位置:生活全書館 >

學習教育

> PHP實現JWT的Token登入認證

PHP實現JWT的Token登入認證

<link rel="stylesheet" href="https://js.how234.com/third-party/SyntaxHighlighter/shCoreDefault.css" type="text/css" /><script type="text/javascript" src="https://js.how234.com/third-party/SyntaxHighlighter/shCore.js"></script><script type="text/javascript"> SyntaxHighlighter.all(); </script>

1、JWT簡介

JSON Web Token(縮寫 JWT),是目前最流行的跨域認證解決方案。

session登入認證方案:使用者從客戶端傳遞使用者名稱、密碼等資訊,服務端認證後將資訊儲存在session中,將session_id放到cookie中。

以後訪問其他頁面,自動從cookie中取到session_id,再從session中取認證資訊。

一類解決方案,將認證資訊,返回給客戶端,儲存到客戶端。下次訪問其他頁面,需要從客戶端傳遞認證資訊回服務端。

JWT就是這類方案的代表,將認證資訊儲存在客戶端。

2、JWT 的原理

JWT 的原理是,伺服器認證以後,生成一個 JSON格式的 物件,發回給客戶端,就像下面這樣。

{"使用者名稱": "admin","角色": "超級管理員","到期時間": "2019-07-13 00:00:00"}

以後,客戶端與服務端通訊的時候,都要發回這個 JSON 物件。伺服器完全只靠這個物件認定使用者身份。

為了防止使用者篡改資料,伺服器在生成這個物件的時候,會加上簽名(詳見後文)。

伺服器不再儲存任何 session 資料,也就是伺服器變成無狀態了,從而比較容易實現擴充套件。

3、JWT 的使用方式

客戶端收到伺服器返回的 JWT,可以儲存在 Cookie 裡面,也可以儲存在 localStorage。

此後,客戶端每次與伺服器通訊,都要帶上這個 JWT。你可以把它放在 Cookie 裡面自動傳送,但是這樣不能跨域,所以更好的做法是放在 HTTP 請求的頭資訊Authorization欄位裡面。

Authorization: Bearer

另一種做法是,跨域的時候,JWT 就放在 POST 請求的資料體裡面。

4、JWT 的幾個特點

(1)JWT 預設是不加密,但也是可以加密的。生成原始 Token 以後,可以用金鑰再加密一次。

(2)JWT 不加密的情況下,不能將祕密資料寫入 JWT。

(3)JWT 不僅可以用於認證,也可以用於交換資訊。有效使用 JWT,可以降低伺服器查詢資料庫的次數。

(4)JWT 的最大缺點是,由於伺服器不儲存 session 狀態,因此無法在使用過程中廢止某個 token,或者更改 token 的許可權。也就是說,一旦 JWT 簽發了,在到期之前就會始終有效,除非伺服器部署額外的邏輯。

(5)JWT 本身包含了認證資訊,一旦洩露,任何人都可以獲得該令牌的所有許可權。為了減少盜用,JWT 的有效期應該設定得比較短。對於一些比較重要的許可權,使用時應該再次對使用者進行認證。

(6)為了減少盜用,JWT 不應該使用 HTTP 協議明碼傳輸,要使用 HTTPS 協議傳輸。

5、功能實現

JWT功能元件

使用composer安裝 JWT 功能元件

composer require lcobucci/jwt 3.3

封裝JWT工具類 

extend/tools/jwt/Token.php

 'http://www.pyg.com',//接收人        'id' => '3f2g57a92aa',//token的唯一標識,這裡只是一個簡單示例        'sign' => 'pinyougou',//簽名金鑰        'issuer' => 'http://adminapi.pyg.com',//簽發人        'expire' => 3600*24 //有效期    ];    //生成token    public static function getToken($user_id){        //簽名物件        $signer = new Sha256();        //獲取當前時間戳        $time = time();        //設定簽發人、接收人、唯一標識、簽發時間、立即生效、過期時間、使用者id、簽名        $token = (new Builder())->issuedBy(self::$_config['issuer'])            ->canOnlyBeUsedBy(self::$_config['audience'])            ->identifiedBy(self::$_config['id'], true)            ->issuedAt($time)            ->canOnlyBeUsedAfter($time-1)            ->expiresAt($time + self::$_config['expire'])            ->with('user_id', $user_id)            ->sign($signer, self::$_config['sign'])            ->getToken();        return (string)$token;    }    //從請求資訊中獲取token令牌    public static function getRequestToken()    {        if (empty($_SERVER['HTTP_AUTHORIZATION'])) {            return false;        }        $header = $_SERVER['HTTP_AUTHORIZATION'];        $method = 'bearer';        //去除token中可能存在的bearer標識        return trim(str_ireplace($method, '', $header));    }    //從token中獲取使用者id (包含token的校驗)    public static function getUserId($token = null)    {        $user_id = null;        $token = empty($token)?self::getRequestToken():$token;        if (!empty($token)) {            //為了登出token 加以下if判斷程式碼            $delete_token = cache('delete_token') ?: [];            if(in_array($token, $delete_token)){                //token已被刪除(登出)                return $user_id;            }            $token = (new Parser())->parse((string) $token);            //驗證token            $data = new ValidationData();            $data->setIssuer(self::$_config['issuer']);//驗證的簽發人            $data->setAudience(self::$_config['audience']);//驗證的接收人            $data->setId(self::$_config['id']);//驗證token標識            if (!$token->validate($data)) {                //token驗證失敗                return $user_id;            }            //驗證簽名            $signer = new Sha256();            if (!$token->verify($signer, self::$_config['sign'])) {                //簽名驗證失敗                return $user_id;            }            //從token中獲取使用者id            $user_id = $token->getClaim('user_id');        }        return $user_id;    }}

修改public/.htaccess檔案,通過apache重寫,處理HTTP請求中的Authorization欄位

(不處理,php中接收不到HTTP_AUTHORAZATION欄位資訊)

RewriteCond %{HTTP:Authorization} ^(.+)$RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

測試: application/adminapi/controller/Index.phpindex方法

靜態呼叫封裝的oolsjwtToken類的getToken方法,傳遞一個使用者id值,生成token

靜態呼叫封裝的oolsjwtToken類的getUserId方法,傳遞一個token,獲取使用者id

PHP實現JWT的Token登入認證

訪問結果

PHP實現JWT的Token登入認證 第2張

到此這篇關於PHP實現JWT的Token登入認證的文章就介紹到這了,希望對大家的學習有所幫助。

標籤: token php 登入 jwt
  • 文章版權屬於文章作者所有,轉載請註明 https://shqsg.com/xuexijiaoyu/z4k3r9.html