环境: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]);}
}
这是完整的步骤,欢迎大家指正。