安装
composer require lcobucci/jwt 3.3
封装
<?php
/**
* author: sanxiao
* datetime: 2019/12/8 17:49
*/
namespace Framework;
use Carbon\Carbon;
use Lcobucci\JWT\Token;
use Lcobucci\JWT\Token\DataSet;
use Lcobucci\JWT\Validation\Constraint\SignedWith;
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Signer\Key;
class Jwt {
protected $header = 'authorization';
protected $prefix = 'bearer';
/**
* @var Key
*/
private $sign_key;
/**
* @var Parser
*/
private $parser;
/**
* @var Builder
*/
private $builder;
/**
* @var Sha256
*/
private $signer;
public function __construct(Parser $parser, Builder $builder)
{
$secret = env('JWT_SECRET');
if (!$secret || $secret == 'APP_KEY') {
$secret = env('APP_KEY', 'sanxiao');
}
$this->sign_key = new Key($secret);
$this->parser = $parser;
$this->builder = $builder;
$this->signer = new Sha256();
}
/**
* 获取JWT
* @param string $id ID
* @param array $ext 扩展信息
* @param Carbon $issuedAt 发行时间
* @param int $ttl 过期时间
* @return string jwt
*/
public function getToken(string $id, array $ext = [], Carbon $issuedAt = null, int $ttl = null) : string
{
$issuedAt = $issuedAt ?? Carbon::now();
$token_ttl = config('jwt.ttl', 86400);
$ttl = $ttl ?? $token_ttl;
$this->builder->issuedAt($issuedAt->toDateTimeImmutable())
->expiresAt($issuedAt->addSeconds($ttl)->toDateTimeImmutable())
->withClaim('id', $id);
foreach ($ext as $key => $val) {
$this->builder->withClaim($key, $val);
}
$token = $this->builder->getToken($this->signer, $this->sign_key);
return $token->toString();
}
/**
* 从头部获取匹配的JWT
* @return mixed
*/
public function parse()
{
$header = request()->header($this->header);
if ($header && preg_match('/'.$this->prefix.'\s*(\S+)\b/i', $header, $matches)) {
return $matches[1];
} else {
return false;
}
}
/**
* 检查Token并返回用户ID
* @return bool|int
*/
public function checkToken()
{
$headerToken = $this->parse();
if (!$headerToken) {
return false;
}
try {
/** @var Token $curToken */
$curToken = $this->parser->parse((string)$headerToken);
$signedWith = new SignedWith($this->signer, $this->sign_key);
$signedWith->assert($curToken);
} catch (\Exception $e) {
return false;
}
$flg = $curToken->isExpired(Carbon::now()->toDateTimeImmutable());
if ($flg) {
return false;
}
if ($curToken->claims()->has('id')) {
$user_id = $curToken->claims()->get('id');
} else {
return false;
}
return $user_id;
}
/**
* 获取扩展信息
* @param string $jwt
* @return DataSet
*/
public function getClaims(string $jwt) : DataSet
{
$token = $this->parser->parse($jwt);
return $token->claims();
}
}
使用
//在控制器中//获取用户id
$user_id = $this->getAuthId();
继承的 BaseController
abstract class BaseController extends Controller
{
use AuthorizesRequests, DispatchesJobs;
use Helper;
/**
* 获取授权用户ID
*/
public function getAuthId() : int
{
return Hope::getLoginId();
}
/**
* 是否登录
* @return bool
*/
public function isLogin() : bool
{
return !!$this->getAuthId();
}
}
公共方法文件
public static function getLoginId(): int
{
$jwt = app(Jwt::class);
$user_id = $jwt->checkToken();
if ($user_id === false) {
return 0;
}
return $user_id;
}
当然以上的代码层次 hope.php 公共类文件所放的文件夹需要在 composer.josn 文件中自动加载。
例如:我习惯放在 framework 文件夹
"autoload": {
"psr-4": {
"App\\": "app/",
"Framework\\": "framework/",
"Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/"
}
},