環境:php8.3\tp8.1\firebase-jwt6.1
app\middleware\JwtAuth
<?php
namespace app\middleware;use app\common\library\JwtHandler;
use think\Request;
use think\facade\Env;class JwtAuth
{public function handle(Request $request, \Closure $next){// 獲取當前請求路徑$path = $request->pathinfo();// 如果是登錄或注冊接口,跳過 Token 校驗if (in_array($path, ['api/auth/login/', 'api/auth/register/'])) {return $next($request);}// 獲取 Authorization 頭$token = $request->header('Authorization');if (!$token) {$this->handleTokenError('Token not provided');}// 如果 Authorization 頭中有 Bearer token,處理它if (str_starts_with($token, 'Bearer ')) {$token = substr($token, 7); // 去掉 'Bearer ' 前綴}try {// 解碼并驗證 Token$data = JwtHandler::getData($token);if (!$data) {$this->handleTokenError('Invalid or expired token');}// 將解碼的用戶數據附加到請求對象$request->user = $data;} catch (\Exception $e) {$this->handleTokenError('Invalid or expired token');}return $next($request);}// 處理 Token 錯誤的公共方法private function handleTokenError($message): void{// 在生產環境中提供簡潔的錯誤信息if (Env::get('app.env') === 'production') {json(['code' => 401,'message' => 'Invalid or expired token']);return;}// 在開發環境中提供詳細的錯誤信息json(['code' => 401,'message' => $message]);}
}
app\common\library\JwtHandler;
<?phpnamespace app\common\library;use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use think\exception\ValidateException;class JwtHandler
{private static string $key = 'quwei'; // 密鑰/*** 生成JWT* @param array $payload* @return string* @throws ValidateException*/public static function encode(array $payload): string{$issuedAt = time(); // 當前時間$expirationTime = $issuedAt + 60; // 設置過期時間為1小時$payload['iat'] = $issuedAt; // 簽發時間$payload['exp'] = $expirationTime; // 過期時間try {// 生成JWTreturn JWT::encode($payload, self::$key, 'HS256');} catch (\UnexpectedValueException $e) {throw new ValidateException('Error encoding JWT: ' . $e->getMessage());}}/*** 解碼JWT* @param string $jwt* @return object|null* @throws ValidateException*/public static function decode(string $jwt): ?object{try {// 解碼JWTreturn JWT::decode($jwt, new Key(self::$key, 'HS256'));} catch (\Firebase\JWT\ExpiredException $e) {throw new ValidateException('Token expired: ' . $e->getMessage());} catch (\UnexpectedValueException $e) {throw new ValidateException('Invalid token: ' . $e->getMessage());} catch (\Exception $e) {throw new ValidateException('Error decoding JWT: ' . $e->getMessage());}}/*** 獲取JWT中的數據* @param string $jwt* @return array|null*/public static function getData(string $jwt): ?array{try {$decoded = self::decode($jwt);return $decoded ? (array)$decoded : null;} catch (ValidateException $e) {return null; // 解碼失敗時返回 null}}
}
app\api\controller\auth.php
<?phpnamespace app\api\controller;use app\BaseController;
use app\common\library\JwtHandler;
use think\Request;
use think\response\Json;class Auth extends BaseController
{/*** 用戶登錄,生成JWT* @param Request $request* @return Json*/public function login(Request $request): Json{$username = $request->post('username');$password = $request->post('password');// 假設你通過用戶名和密碼來驗證用戶if ($username === 'John' && $password === '123') {// 生成 JWT,payload 可以根據需要調整$payload = ['sub' => 1, // 用戶ID'name' => $username,'role' => 'admin'];// 生成JWT$jwt = JwtHandler::encode($payload);return json(['code' => 200, 'message' => 'Login successful', 'token' => $jwt]);}return json(['code' => 400, 'message' => 'Invalid credentials'], 400);}/*** 驗證JWT,獲取用戶信息* @param Request $request* @return Json*/public function me(Request $request): Json{$token = $request->header('Authorization'); // 獲取Authorization頭中的Tokenif (!$token) {return json(['code' => 401, 'message' => 'Token not provided'], 401);}// 解碼Tokentry {$data = JwtHandler::getData($token);if ($data) {return json(['code' => 200, 'message' => 'Success', 'data' => $data]);}return json(['code' => 401, 'message' => 'Invalid or expired token'], 401);} catch (\Exception $e) {return json(['code' => 401, 'message' => 'Invalid or expired token'], 401);}}public function getUserProfile(Request $request): Json{// 直接訪問解碼后的用戶信息$user = $request->user;// 返回當前用戶的個人資料return json(['code' => 200, 'data' => $user]);}
}
這是完整的步驟,歡迎大家指正。