一,安裝firebase/php-jwt擴展:
1,命令:
liuhongdi@lhdpc:/data/php/admapi$ composer require firebase/php-jwt
2,安裝成功后的位置:

3,查看firebase/php-jwt的版本:
liuhongdi@lhdpc:/data/php/admapi$ composer show firebase/php-jwt

說明:劉宏締的架構森林是一個專注架構的博客,
網站:https://blog.imgtouch.com
本文: https://blog.imgtouch.com/index.php/2023/05/29/thinkphp6-qian-hou-duan-fen-li-yong-jwt-middleware-zuo-yong/
對應的源碼可以訪問這里獲取: https://github.com/liuhongdi/
或: https://gitee.com/liuhongdi
說明:作者:劉宏締 郵箱: 371125307@qq.com
二,前端vue代碼:
Login.vue
<template> <div style="padding:20px;display: flex;align-items:center;justify-content: center;"> <form :model="account" style="margin-top:50px;width:400px;"> <input v-model="account.username" placeholder="請輸入用戶名" style="width:392px;font-size:16px;" /><br/> <input v-model="account.password" type="password" placeholder="請輸入密碼" style="width:392px;margin-top:10px;font-size:16px;" /><br/> <!--v-loading.fullscreen.lock="isLoading"--> <div @click="login" style="margin-top:10px;width: 100%;height:40px;line-height:40px;background: #ff0000;border-radius: 10px;"> 登錄 </div> <div @click="info" style="margin-top:10px;width: 100%;height:40px;line-height:40px;background: #ff0000;border-radius: 10px;"> info </div> <div class="text-align-right"> </div> </form> </div> </template> <script> import { ref, reactive } from "vue"; import { ElMessage } from "element-plus"; import { apiLogin,apiInfo,apiToken} from '@/api/api'; export default { name: "Login", setup() { const accountRef = ref(null); //表單字段 const account = reactive({ username: "", password: "", }); //登錄 const login = async () => { console.log('begin login'); var data = new FormData(); data.append("username",account.username); data.append("password",account.password); apiLogin(data).then(res => { //成功 if (res.code == 0) { //保存jwt token到本地 localStorage.setItem('token', res.data.token); //提示 ElMessage.success("登錄成功!"); } else { ElMessage.error("登錄失敗:"+res.msg); } }).catch((error) => { console.log(error) }) }; const login2 = () => { console.log('begin login2'); } const info = () => { apiInfo().then(res => { //成功 if (res.code == 0) { //保存jwt token到本地 //localStorage.setItem('token', res.data.token); //提示 //ElMessage.success("登錄成功!"); console.log(res.data); } else { ElMessage.error("用戶信息獲取失敗:"+res.msg); } }).catch((error) => { console.log(error) }) } return { account, //loginRules, accountRef, login, login2, info, //isLoading, }; }, } </script> <style scoped> </style>
三,后端php代碼:
1,創建middleware
liuhongdi@lhdpc:/data/php/admapi$ php think make:middleware CheckJwt Middleware:app\middleware\CheckJwt created successfully.
2,CheckJwt的代碼:
<?php declare (strict_types = 1); namespace app\middleware; use app\lib\util\JwtUtil; class CheckJwt { /** * 處理請求,得到用戶信息 * * @param \think\Request $request * @param \Closure $next * @return Response */ public function handle($request, \Closure $next) { $auth = $request->header('authorization'); if ($auth == null) { return $next($request); } $token = str_replace("Bearer ","",$auth); $jUtil = new JwtUtil(); $res = $jUtil->verifyjwt($token); if (isset($res['code']) && isset($res['userId']) && $res['code'] == 0 && is_int($res['userId'])) { $userId = $res['userId']; $request->auth = $userId; } else { $request->auth = 0; } return $next($request); } }
3,app/middleware.php
使從jwt得到用戶信息的middleware生效:
<?php // 全局中間件定義文件 return [ app\middleware\CheckJwt::class, ];
4,controller/Auth.php
<?php declare (strict_types = 1); namespace app\controller; use app\BaseController; use think\facade\Cache; use think\Request; use app\result\Result; use think\response\Json; use app\validate\Login as LoginValidate; use app\validate\GoodsList as GoodsListValidate; use think\exception\ValidateException; use app\lib\util\JwtUtil; class Auth extends BaseController { /** * 登錄 * * @return \think\Response */ public function login():Json { try { validate(LoginValidate::class) //->scene('edit') ->check($_POST); } catch (ValidateException $e) { // 驗證失敗 輸出錯誤信息 return Result::Error(422,$e->getError()); } if ($_POST["username"] == "dddddd" && $_POST["password"] == "111111"){ //驗證成功,生成jwt返回 $userId = 123; $jUtil = new JwtUtil(); $token = $jUtil->createJwt($userId); $res = ["token"=>$token]; // 防止重復提交 Cache::delete($key); return Result::Success($res); } else { return Result::Error(422,"用戶名密碼錯誤"); } } /** * 得到用戶信息 * * @return \think\Response */ public function info() { if ($this->request->auth > 0) { $status = "已登錄"; } else { $status = "未登錄"; } $info = [ 'userId'=>$this->request->auth, 'status'=>$status, ]; return Result::Success($info); } }
5,lib/util/JwtUtil.php
<?php namespace app\lib\util; use Firebase\JWT\ExpiredException; use Firebase\JWT\JWT; class JwtUtil { private $signKey = "lhd@2001:liuhongdi"; private $timeMinutes = 5; /** * 根據json web token設置的規則生成token * @return \think\response\Json */ public function createJwt($userId):string { $key = md5($this->signKey); //jwt的簽發**,驗證token的時候需要用到 $time = time(); //簽發時間 $expire = $time + $this->timeMinutes*60; //過期時間 $token = array( "userId" => $userId, "iss" => "http://www.liuhongdi.com/",//簽發組織 "aud" => "lhd", //簽發作者 "iat" => $time, //簽發時間 "nbf" => $time, //生效時間 "exp" => $expire //過期時間 ); $jwt = JWT::encode($token,$key); return $jwt; } /** * 驗證token * @return \think\response\Json */ public function verifyjwt($token) { $key = md5($this->signKey); //jwt的簽發**,驗證token的時候需要用到 try{ $jwtAuth = json_encode(JWT::decode($token,$key,array("HS256"))); $authInfo = json_decode($jwtAuth,true); if (!$authInfo['userId']){ return ['code'=>0,'msg'=>"用戶不存在"]; } return ['code'=>0,'userId'=>$authInfo['userId'],'msg'=>"ok"]; }catch (ExpiredException $e){ return ['code'=>0,'msg'=>"token過期"]; }catch (\Exception $e){ return ['code'=>0,'msg'=>$e->getMessage()]; } } }
四,效果測試
1,界面:用戶名 dddddd,密碼;111111,可見php的代碼:
2,未登錄時點info
3,登錄后的返回:

4,登錄后查看info的返回:

五,查看php和thinkphp的版本:
php:
liuhongdi@lhdpc:/data/php/admapi$ php --version PHP 8.1.1 (cli) (built: Dec 20 2021 16:12:16) (NTS) Copyright (c) The PHP Group Zend Engine v4.1.1, Copyright (c) Zend Technologies with Zend OPcache v8.1.1, Copyright (c), by Zend Technologies
thinkphp:
liuhongdi@lhdpc:/var/www/html$ cd /data/php/admapi/ liuhongdi@lhdpc:/data/php/admapi$ php think version v6.0.10LTS