php接口數據安全解決方案(二)


前言

JWT是什么
JWT是json web token縮寫。它將用戶信息加密到token里,服務器不保存任何用戶信息。服務器通過使用保存的密鑰驗證token的正確性,只要正確即通過驗證。基於token的身份驗證可以替代傳統的cookie+session身份驗證方法。
它定義了一種用於簡潔,自包含的用於通信雙方之間以 JSON 對象的形式安全傳遞信息的方法。JWT 可以使用 HMAC 算法或者是 RSA 的公鑰密鑰對進行簽名。

本實例是使用github開源項目來實現,項目地址為
點擊查看源jwt項目代碼

怎么使用jwt項目?

  • 1.閱讀GitHub上項目文檔說明
  • 2.composer安裝jwt(composer require lcobucci/jwt)
  • 3.引用vendor中autoload.php文件實現jwt類自動加載

實例演示token簽名並創建token

<?php
include "./vendor/autoload.php";
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Signer\Hmac\Sha256;

$time = time();
$token = (new Builder())->setHeader('alg','HS256')
//配置發行者
->setIssuer("jwtTest")
//配置Audience
->setAudience("php")
//配置令牌發出的時間(簽發時間)
->setIssuedAt($time)
//配置令牌該時間之前不接收處理該Token
->setNotBefore($time+60)
//配置令牌到期的時間
->setExpiration($time + 7200)
//配置一個自定義uid聲明
->set('uid',20)
//使用sha256進行簽名,密鑰為123456
->sign(new Sha256(),"123456")
//獲取token
->getToken();
// echo $token;
//獲取設置所有header頭
$headers = $token->getHeaders();    
//獲取所有的配置
$claims = $token->getClaims();

$alg = $token->getHeader('alg');
$iss = $token->getClaim('iss');
$aud = $token->getClaim('aud');
$iat = $token->getClaim('iat');
$exp = $token->getClaim('exp');
$nbf = $token->getClaim('nbf');
$uid = $token->getClaim('uid');

echo "=====下面是設置的header頭信息======<br/>";
echo "當前token的alg鹽值為{$alg}<br/>";

echo "=====下面是所有配置信息<br/>";
echo "當前token的發行者是:{$iss}<br/>";
echo "當前token的Audience是:{$aud}<br/>";
echo "當前token的令牌發出時間是:{$iat}<br/>";
echo "當前token不接收處理的時間為:{$nbf}<br/>";
echo "當前token的到期時間:{$exp}<br/>";
echo "當前token的uid是:{$uid}<br/>";
echo "當前token字符串為:{$token}";

結果展示:

=====下面是設置的header頭信息======
當前token的alg鹽值為HS256
=====下面是所有配置信息
當前token的發行者是:jwtTest
當前token的Audience是:php
當前token的令牌發出時間是:1563246935
當前token不接收處理的時間為:1563246995
當前token的到期時間:1563254135
當前token的uid是:20
當前token字符串為:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqd3RUZXN0IiwiYXVkIjoicGhwIiwiaWF0IjoxNTYzMjQ2OTM1LCJuYmYiOjE1NjMyNDY5OTUsImV4cCI6MTU2MzI1NDEzNSwidWlkIjoyMH0.O8tscKPweCvSaXkOVbmhtEcsJ7BWRxRn9s_xXFstgsE

解析token並校驗token合法性

<?php
include "./vendor/autoload.php";
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\ValidationData;

//解析token
$token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqd3RUZXN0IiwiYXVkIjoicGhwIiwiaWF0IjoxNTYzMjQ2Mjc4LCJuYmYiOjE1NjMyNDYzMzgsImV4cCI6MTU2MzI1MzQ3OCwidWlkIjoyMH0.1XSZW6aWrHplAlMPMpc1K5gKdpWYE7AMa6T7qhBTF30';

//解析后的token對象
$decodeToken = (new Parser())->parse((string) $token);
$uid = $decodeToken->getClaim('uid');
$exp = $decodeToken->getClaim('exp');
$time = time();
echo "當前時間為:{$time}<br/>";
$result = $decodeToken->verify(new Sha256(),"123456");

//對token進行發行者和audience的校驗
$data = new ValidationData();
$data->setAudience("php");
$data->setIssuer("jwtTest");
$resultVali =  $decodeToken->validate($data);
// print_r($resultVali);

//判斷token簽名和校驗發行者是否合法
if($result && $resultVali){
    //如果設置的token有效時間大於當前時間則表示token過期了
    if($time>$exp){
        echo "該token已經過期了<br/>";    
    }else{
        echo "該token是合法的uid為:{$uid},過期時間為{$exp}<br/>";
    }
}else{
    echo "該token不合法簽名錯誤或發行者不合法<br/>";
}

運行后結果為:

當前時間為:1563248373
該token是合法的uid為:20,過期時間為1563253478

類庫封裝管理jwt實例

<?php
include "./vendor/autoload.php";
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\ValidationData;
use Lcobucci\JWT\Claim\GreaterOrEqualsTo;
use Lcobucci\JWT\Token;

/**
 * Class JwtAuth
 * @package App\Library
 * @desc jwt接口鑒權類處理
 */
class JwtAuth{
    //jwt token
    private $token;
    /**
     * @var 用戶傳遞的decode token
     */
    private $decodeToken;
    private static $_instance;
    private $iss = "jwtTest";
    private $aud = "php";
    private $uid;
    private $serect = "123456";
    private $exp;//token失效時間
    const EXP = 60;//token有效時間一個月

    /**
     * JwtAuth constructor.
     * 私有化construct方法
     */
    private function __construct()
    {
    }

    /**
     * 私有化clone方法
     */
    private function __clone()
    {
        // TODO: Implement __clone() method.
    }

    /**
     *  獲取jwtauth類實例化對象
     */
    public static function getInstance(){
        if(!(self::$_instance instanceof JwtAuth) ){
            self::$_instance = new JwtAuth();
        }
        return self::$_instance;
    }

    /**
     * 獲取token
     * @return string
     */
    public function getToken(){
        return (string)$this->token;
    }

    /**
     * 設置token
     * @param $token
     * @return $this
     */
    public function setToken($token){
        $this->token = $token;
        return $this;
    }

    /**
     * 設置uid
     * @param $uid
     * @return $this
     */
    public function setUid($uid){
        $this->uid = $uid;
        return $this;
    }

    /**
     * 獲取uid
     * @return mixed
     */
    public function getUid(){
        return $this->uid;
    }

     /**
     * 獲取exp
     * @return mixed
     */
    public function getExp(){
        return $this->exp;
    }

    /**
     * 編碼jwt token
     */
    public function encode(){
        $time = time();
        $this->token = (new Builder())->setHeader('alg','HS256')
            ->setIssuer($this->iss)
            ->setAudience($this->aud)
            ->setIssuedAt($time)
            ->setExpiration($time + self::EXP)
            ->set('uid',$this->uid)
            ->sign(new Sha256(),$this->serect)
            ->getToken();
        return $this;
    }

    /**
     * 解析傳遞的token
     * @return 用戶傳遞的decode
     */
    public function decode(){
        if(!$this->decodeToken){
            // Parses from a string
            $this->decodeToken = (new Parser())->parse((string) $this->token);
            $this->uid = $this->decodeToken->getClaim('uid');
            $this->exp = $this->decodeToken->getClaim('exp');
//            error_log('exp:'.$this->decodeToken->getClaim('exp'));
//            error_log('uid:'.$this->decodeToken->getClaim('uid'));
        }
        return $this->decodeToken;
    }

    /**
     * verify校驗token signature串第三個字符串
     * @return mixed
     */
    public function verify(){
        $result = $this->decode()->verify(new Sha256(),$this->serect);
        return $result;
    }

    /**
     * 校驗傳遞的token是否有效,校驗前兩個字符串
     * @return mixed
     */
    public function validate(){
        $data = new ValidationData();
        $data->setAudience($this->aud);
        $data->setIssuer($this->iss);
        return $this->decode()->validate($data);
    }

}

/*
@desc 模擬登錄返回token
 */
$jwtAuth = JwtAuth::getInstance();
$uid = 20;
$token = $jwtAuth->setUid($uid)->encode()->getToken();
echo "當前已經為您生成最新token:{$token}<br/>";


/*
1.解析token
2.校驗token簽名是否合法
3.驗證token發行者等信息是否合法
4.校驗token是否過期
 */
$token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqd3RUZXN0IiwiYXVkIjoicGhwIiwiaWF0IjoxNTYzMjY4NjExLCJleHAiOjE1NjMyNjg2NzEsInVpZCI6MjB9.PeEA3xTE2lKl4YCYQ2cjHSNYsrJ24HRnW1-yKM-LgHc';
$jwtAuth2 = JwtAuth::getInstance();
$jwtAuth2->setToken($token);
if($jwtAuth2->validate() && $jwtAuth2->verify()){
    //初始化用戶id
    $uid = $jwtAuth2->getUid();
    $exp = $jwtAuth2->getExp();
    echo "token合法,您當前的uid為:{$uid},當前時間戳為:".time()."token有效時間為:{$exp}<br/>";
}else{
    echo "token校驗失敗,token簽名不合法,或token發行者信息不合法<br/>";
}

演示結果為

當前已經為您生成最新token:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqd3RUZXN0IiwiYXVkIjoicGhwIiwiaWF0IjoxNTYzMjY4NjIzLCJleHAiOjE1NjMyNjg2ODMsInVpZCI6MjB9.BrsVElhVkTIq5xH3-JpvqvawNhDALb98VYZGbMTzWV8
token合法,您當前的uid為:20,當前時間戳為:1563268623token有效時間為:1563268671
當前已經為您生成最新token:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqd3RUZXN0IiwiYXVkIjoicGhwIiwiaWF0IjoxNTYzMjY4NzA1LCJleHAiOjE1NjMyNjg3NjUsInVpZCI6MjB9.juTM5iG8LNDid8Sp4jOjtHeTitaIB2WxZeW3GjnQrB0
token校驗失敗,token簽名不合法,或token發行者信息不合法


免責聲明!

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



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