乐趣区

Yii-使用JWT

了解 JWT 可以参考:了解 JWT

一:下载 JWT 拓展

在 JWT 官网中我们可以看到很多 php 版本的 JWT,选择一个 JWT 进行下载

这里我选择的是 lcobucci/jwt,使用 composer 进行下载

lcobucci/jwt 的 composer 地址:https://packagist.org/package…

composer require lcobucci/jwt "^3.3.0"  #这里我下载的是 3.3.0 版本 

二:lcobucci/jwt 使用

lcobucci/jwt 使用方法可以参考下载下来的 README.md 文件 (vendor/lcobucci/jwt/README.md)

1:生成 JWT

$request = Yii::$app->getRequest();
$signer = new Sha256();// 使用 Sha256 加密,常用加密方式有 Sha256,Sha384,Sha512
$time = time();
$tokenBuilder = (new Builder())
    ->issuedBy($request->getHostInfo()) // 设置发行人
    ->permittedFor(isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : '') // 设置接收
    ->identifiedBy(Yii::$app->security->generateRandomString(10), true) // 设置 id
    ->issuedAt($time) // 设置生成 token 的时间
    ->canOnlyBeUsedAfter($time) // 设置 token 使用时间 (实时使用)
    ->expiresAt($time + 3600); // 设置 token 过期时间
// 定义自己所需字段
$user = ['user_name' => '测试', 'user_no' => '001'];
$tokenBuilder->withClaim('user', $user);
$tokenBuilder->withClaim('ceshi', '测试字段');
// 使用 Sha256 加密生成 token 对象,该对象的字符串形式为一个 JWT 字符串
$token = $tokenBuilder->getToken($signer, new Key('jwt_secret'));
echo (string) $token;

2:对 JWT 进行校验

在正常的开发环境下,我们将生成的 JWT 字符串传到前端,当前端调用其他接口时,将我们所给的 JWT 传递到后台,我们后台需要对前端传来的 JWT 字符串进行校验

下面的 $token 为我们获取到的前端传递的 JWT

$token = (new Parser())->parse($token);
// 数据校验
$data = new ValidationData(); // 使用当前时间来校验数据
if (!$token->validate($data)) {
    // 数据校验失败
    return '数据校验失败';
}
//token 校验
$signer = new Sha256();// 生成 JWT 时使用的加密方式
if (!$token->verify($signer, new Key('jwt_secret'))) {
    //token 校验失败
    return 'token 校验失败';
}
echo '校验成功';

3:获取 JWT 的相关信息

$token = (new Parser())->parse($token);
$token->getHeaders(); // 获取 JWT 的 Header( 头部) 信息
$token->getClaims(); // 获取 JWT 的 PayLoad( 负载) 信息
// 获取指定参数的 PayLoad(负载) 信息
$token->getClaim('jti');
$token->getClaim('user');

三:编写一个 JWT 类,方便对于 JWT 的使用

1:创建一个 JWT 类,代码如下:

<?php
/**
 * author: wangjian
 * date: 2019/6/24
 */
namespace app\components;

use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Claim\Factory as ClaimFactory;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Parsing\Decoder;
use Lcobucci\JWT\Parsing\Encoder;
use Lcobucci\JWT\Signer\Key;
use Lcobucci\JWT\Token;
use Lcobucci\JWT\ValidationData;
use Yii;
use yii\base\Component;
use yii\base\InvalidParamException;

/**
 * JWT 通用方法
 * Class JWT
 * @package app\components
 */
class JWT extends Component
{

    /**
     * @var array 支持的加密算法
     */
    public $supportedAlgs = [
        'HS256' => 'Lcobucci\JWT\Signer\Hmac\Sha256',
        'HS384' => 'Lcobucci\JWT\Signer\Hmac\Sha384',
        'HS512' => 'Lcobucci\JWT\Signer\Hmac\Sha512',
    ];
    
    /**
     * 实例化 JWT 生成器
     * @see [[Lcobucci\JWT\Builder::__construct()]]
     * @return Builder
     */
    public function getBuilder(Encoder $encoder = null, ClaimFactory $claimFactory = null)
    {return new Builder($encoder, $claimFactory);
    }
    
    /**
     * 实例化 JWT 分析器
     * @see [[Lcobucci\JWT\Parser::__construct()]]
     * @return Parser
     */
    public function getParser(Decoder $decoder = null, ClaimFactory $claimFactory = null)
    {return new Parser($decoder, $claimFactory);
    }
    
    /**
     * 验证 JWT 并返回一个令牌类
     * function: ValiJwt
     * @return Token|null
     */
    public function ValiJwt($token, $validate = true, $verify = true)
    {
        try {$token = $this->getParser()->parse((string)$token);
        } catch (\RuntimeException $e) {// Yii::warning("Invalid JWT provided:" . $e->getMessage(), 'jwt');
            return null;
        } catch (\InvalidArgumentException $e) {// Yii::warning("Invalid JWT provided:" . $e->getMessage(), 'jwt');
            return null;
        }
        if ($validate && !$this->validateToken($token)) {return null;}
        if ($verify && !$this->verifyToken($token)) {return null;}
        return $token;
    }
    
    /**
     * 数据验证
     * Validate token
     * @param Token $token token object
     * @return bool
     */
    public function validateToken(Token $token, $currentTime = null)
    {$data = new ValidationData($currentTime);
        // @todo Add claims for validation
        return $token->validate($data);
    }
    
    /**
     * Validate token
     * @param Token $token token object
     * @return bool
     */
    public function verifyToken(Token $token)
    {$alg = $token->getHeader('alg');
        if (empty($this->supportedAlgs[$alg])) {throw new InvalidParamException('Algorithm not supported');
        }
        $signer = Yii::createObject($this->supportedAlgs[$alg]);
        return $token->verify($signer, new Key('jwt_secret'));
    }
    
}

2: 在配置文件中添加 (引入 JWT 类):

'components' => [
...
'jwt' => ['class' => 'app\components\Jwt'],
...
]

3:使用:

Yii::$app->jwt
Yii::$app->jwt->getBuilder() #等同于 new Builder() 
Yii::$app->jwt->ValiJwt($token);JWT 验证 
退出移动版