我的PHP版本为PHP8.3,nginx版本为1.25,所以官方默认下载4.0版本
1、首先安装JWT扩展包:这里安装的4.0的,其他版本请查看JWT官网:https://jwt.io/libraries
composer require lcobucci/jwt
2、封装类:JwtUtil.php
在项目http目录下创建JwtAuth目录,并创建JwtUtil.php文件
<?php
namespace App\Http\JwtAuth;
use Lcobucci\JWT\Configuration;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Signer\Key\InMemory;
/**
* 单例模式
* Class JwtUtil
* @package App\JwtAuth\JwtUtil
*/
class JwtUtil
{
private $config;
private $key = "Ge1KCTRhdVsmUUZY0GrwgEvLubPvLOCM";
private $iss = "tpxhm.com";//颁发者(iss声明)
private $aud = "tpxhmauth.com";//访问群体(aud声明)
private $jti = "5t6y9400453"; //id(jti声明)
private $expTime = 1;//令牌有效时间,单位小时
private static $instance;// 单例模式JwtAuth句柄
// 获取JwtAuth的句柄
public static function getInstance()
{
if (is_null(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
/**
* 构造
*/
public function __construct()
{
self::init();
}
/**
* 初始化
*/
private function init()
{
$config = Configuration::forSymmetricSigner(
new Sha256(),
InMemory::base64Encoded($this->key)
);
$this->config = $config;
}
/**
* 创建JWT
* @param array $arrClaim
* @return string
* @throws \Exception
* @author 简忆博客
*/
public function createToken(array $arrClaim)
{
$config = $this->config;
assert($config instanceof Configuration);
if (is_array($arrClaim) && count(array_filter(array_keys($arrClaim),'is_string'))>0) {
//是关联数组
} else {
//不是关联数组
throw new \Exception("claim参数必须为关联数组");
}
$now = new \DateTimeImmutable();
$token = $config->builder()
// 配置颁发者(iss声明)
->issuedBy($this->iss)
// 配置访问群体(aud声明)
->permittedFor($this->aud)
// 配置id(jti声明)
->identifiedBy($this->jti)
// 配置令牌发出的时间(iat声明)
->issuedAt($now)
// 配置令牌的过期时间(exp claim)
->expiresAt($now->modify("+{$this->expTime} hour"));
//claim
foreach ($arrClaim as $k => $item) {
$token = $token->withClaim($k, $item);
}
// 生成新令牌
$token = $token->getToken($config->signer(), $config->signingKey());
return $token->toString();
}
/**
* 解析token
* @param string $jwt
* @return mixed
* @author 简忆博客
*/
public function parseToken(string $jwt)
{
$config = $this->config;
$token = $config->parser()->parse($jwt);
return $token->claims();
}
/**
* 验证令牌
* @param $jwt
* @return mixed
* @throws \Exception
* @author 简忆博客
*/
public function validatorToken($jwt)
{
$config = $this->config;
$token = $config->parser()->parse($jwt);
$claims = $token->claims();
$jti = (string)$claims->get('jti');
$iss = (string)$claims->get('iss');
$aud = $claims->get('aud');
$exp = $claims->get('exp');
$now = new \DateTimeImmutable();
// 是否过期
if ($exp < $now) {
throw new \Exception("身份已过期");
}
//验证jwt id是否匹配
$validate_jwt_id = new \Lcobucci\JWT\Validation\Constraint\IdentifiedBy($jti);
// 验证签发人url是否正确
$validate_issued = new \Lcobucci\JWT\Validation\Constraint\IssuedBy($iss);
// 验证客户端url是否匹配
$validate_aud = new \Lcobucci\JWT\Validation\Constraint\PermittedFor($aud[0]);
$config->setValidationConstraints($validate_jwt_id, $validate_issued, $validate_aud);
$constraints = $config->validationConstraints();
//验证
if (!$config->validator()->validate($token, ...$constraints)) {
throw new \Exception("非法的请求");
}
return $claims;
}
}
3、创建middleware中间件
<?php
namespace App\Http\Middleware;
use App\Http\JwtAuth\JwtUtil;
use App\Http\Response\ApiErrDesc;
use App\Http\Response\ResponseJson;
use Closure;
use Illuminate\Http\Request;
class CheckLogins
{
use ResponseJson;
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
$token =!empty($_SERVER['HTTP_TOKEN']) ? $_SERVER['HTTP_TOKEN'] : '';
if ($token) {
//检验token
$jwtAuth = JwtUtil::getInstance();
$jwtAuth = $jwtAuth->validatorToken($token);
if($jwtAuth){
return $next($request);
}else {
return $this->jsonData(ApiErrDesc::EXPIRES_TIME[0], ApiErrDesc::EXPIRES_TIME[1]);
}
} else {
return $this->jsonData(ApiErrDesc::LOGIN_TOKEN[0], ApiErrDesc::LOGIN_TOKEN[1]);
}
}
}
4、创建登录控制器:LoginController.php
<?php
namespace App\Http\Controllers\Admin;
use App\Http\JwtAuth\JwtUtil;
use App\Http\Response\ApiErrDesc;
use App\Http\Controllers\Controller;
use App\Http\Requests\Api\CheckCaptcha;
use App\Http\Response\ResponseJson;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class LoginController extends Controller
{
use ResponseJson;
/*
* 用户登录
*
* @param Request $request
* @return false|string
* */
public function login(Request $request){
//获取客户端传递的参数
$name = $request->input('username');
$password = $request->input('password');
try {
//去数据库中查询改用户信息
$res=DB::table('sys_admin')->where(array('name'=>$name,'stop'=>0))->first();
if(!$res){
return $this->jsonData(ApiErrDesc::NO_USER[0],ApiErrDesc::NO_USER[1]);
}
}catch (\Illuminate\Database\QueryException $exception){
return $this->jsonData(ApiErrDesc::ERROR[0],$exception->getMessage());
}
//password_hash()
$userPasswordHash = $res->password;
if(!password_verify($password,$userPasswordHash)){
return $this->jsonData(ApiErrDesc::ERR_PASSWORD[0],ApiErrDesc::ERR_PASSWORD[1]);
}
//验证成功,生成jwt返回
$token = JwtUtil::getInstance()->createToken(['uid' => $res->id]);
//登录成功
return $this->jsonData(ApiErrDesc::LOGIN_SUCCESS[0],ApiErrDesc::LOGIN_SUCCESS[1],$token);
}
}
5、查询用户信息
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Http\JwtAuth\JwtAuth;
use App\Http\JwtAuth\JwtUtil;
use App\Http\Response\ApiErrDesc;
use App\Http\Response\ResponseJson;
class PictureController extends Controller
{
use ResponseJson;
public function info(){
//检验token
$token =!empty($_SERVER['HTTP_TOKEN']) ? $_SERVER['HTTP_TOKEN'] : '';
if (!$token){
return $this->jsonData(ApiErrDesc::LOGIN_TOKEN[0], ApiErrDesc::LOGIN_TOKEN[1]);
}
$jwtAuth = JwtUtil::getInstance();
$claims = $jwtAuth->validatorToken($token);
//得到用户id
$uid = $claims->get('uid');
$user = DB::table('sys_admin')->where('id',$uid)->first();
if(!$user){
return $this->jsonData(ApiErrDesc::NO_USER[0],ApiErrDesc::NO_USER[1]);
}
}
}