Laravel10使用JWT生成Token及验证Token实现登录功能

2024-06-13   阅读:252   分类:后端    标签: Laravel

博主PHP环境为PHP8.2,所以官方默认下载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]);
    }
  }
}

一个简单的案例供大家参考,laravel8的请参考这边文章:Laravel8使用jwt+redis+mysql 实现登录功能

【腾讯云】2核2G云服务器新老同享 99元/年,续费同价,云服务器3年机/5年机限时抢购,低至 2.5折

‘简忆博客’微信公众号 扫码关注‘简忆博客’微信公众号,获取最新文章动态
转载:请说明文章出处“来源简忆博客”。http://www.tpxhm.com/adetail/1066.html

×
觉得文章有用就打赏一下文章作者
微信扫一扫打赏 微信扫一扫打赏
支付宝扫一扫打赏 支付宝扫一扫打赏

文章评论(0)

登录
简忆博客壁纸一
简忆博客壁纸二
简忆博客壁纸三
简忆博客壁纸四
简忆博客壁纸五
简忆博客壁纸六
简忆博客壁纸七
简忆博客壁纸八
头像

简忆博客
勤于学习,乐于分享

置顶推荐

打赏本站

如果你觉得本站很棒,可以通过扫码支付打赏哦!
微信扫码:你说多少就多少~
微信扫码
支付宝扫码:你说多少就多少~
支付宝扫码
×