Thinkphp8使用Jwt生成与验证Token

Thinkphp8使用Jwt

一、宝塔切换PHP版本

安装jwt出现php版本不兼容的问题

bash 复制代码
composer require firebase/php-jwt

firebase/php-jwt依赖包要求PHP≥8.0.0,而当前Composer默认使用了PHP 7.4环境导致版本不兼容

1. 查看已安装版本

bash 复制代码
ls /www/server/php 

2. 切换版本(以PHP8.3为例)

bash 复制代码
rm -f /usr/bin/php
ln -sf /www/server/php/83/bin/php /usr/bin/php

3. 验证结果

bash 复制代码
php -v  # 应显示"PHP 8.3.x"‌

二、创建并使用JWT密钥生成命令的完整流程

1、创建自定义命令

1、生成命令文件‌

执行命令后会在app/command目录生成JwtKeyGenerate.php文件‌

bash 复制代码
php think make:command JwtKeyGenerate

2、编辑命令逻辑‌

修改生成的文件实现密钥生成功能‌

bash 复制代码
   <?php
   namespace app\command;
   use think\console\Command;
   use think\console\Input;
   use think\console\Output;

   class JwtKeyGenerate extends Command
   {
       protected function configure()
       {
           $this->setName('jwt:keygen')
               ->setDescription('Generate JWT secret key');
       }

       protected function execute(Input $input, Output $output)
       {
           $key = bin2hex(random_bytes(32)); // 生成256位密钥
           $output->writeln('Generated JWT Secret:');
           $output->writeln('<info>'.$key.'</info>');
           
           // 可选:自动写入.env文件
           if (file_exists('.env')) {
               file_put_contents('.env', "\nJWT_SECRET=$key\n", FILE_APPEND);
               $output->writeln('Key has been saved to .env');
           }
       }
   }
   

该代码会生成加密强度足够的随机密钥,并支持自动写入环境变量文件‌。

2、注册与使用命令

1、注册到控制台

在config/console.php中添加命令注册‌

bash 复制代码
'commands' => [
    'jwt:keygen' => 'app\command\JwtKeyGenerate'
]

‌2、执行命令‌

运行以下命令生成密钥‌

bash 复制代码
php think jwt:keygen

输出示例:

三、生成token与验证token

1、在config下面创建jwt.php文件,获取生成的jwt密钥secret_key。

bash 复制代码
<?php
// config/jwt.php
return [
    'secret_key' => env('JWT_SECRET', 'fallback_key'), // 必须设置默认值, // 确保这个密钥在生产环境中是安全的
    'expiry'     => 3600, // Token过期时间,单位秒
];
?>

2、在app/common下面创建token.php文件,封装Token生成和验证方法

bash 复制代码
<?php
namespace app\common;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;

class Token {
    

    // 生成Token
    public static function generate(array $payload, int $expire = 7200): string {
        $payload = array_merge($payload, [
            "iss" => 'wuzhicong',    // 签发者
            "iat" => time(),        // 签发时间
            "nbf" => time(),        // 生效时间(立即生效)
            "exp" => time() + $expire, // 过期时间(默认2小时)
        ]);
        $key = config('jwt.secret_key');
        return JWT::encode($payload, $key, 'HS256');
    }

    // 验证Token
    public static function verify(string $token): array {
        try {
            $key = config('jwt.secret_key');
            $decoded = JWT::decode($token, new Key($key, 'HS256'));
            return (array)$decoded;
        } catch (\Exception $e) { // 捕获过期、签名无效等异常
            throw new \Exception("Token验证失败: " . $e->getMessage());
        }
    }
}

3、在app/controller创建Login文件,调用封装token类,生成及验证token

bash 复制代码
<?php
namespace app\controller;
use think\facade\Request;
use think\facade\Config;
use app\common\Token; // 确保引入了JwtToken类
use think\exception\HttpResponseException;
use think\Response;
use think\response\Json;
use think\facade\Route; // 如果需要重定向或者设置cookie等操作,可能需要引入Route类。


class login 
{
    public function login() {
        // 生成Token(包含用户ID)
        $token = Token::generate(['user_id' => '20']);
        return json(['code' => 200, 'token' => $token]);
    }
    
    public function yztoken(){
        // $token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiMjAiLCJpc3MiOiJ0aGlua3BocCIsImlhdCI6MTc1MzE3MzIzNCwibmJmIjoxNzUzMTczMjM0LCJleHAiOjE3NTMxODA0MzR9.vGhXxIuEgXk5fJ_L6h5GbCwePb1Zyv3tVlYEy4ZR9BQ';
        $token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiMjAiLCJpc3MiOiJ3dXpoaWNvbmciLCJpYXQiOjE3NTMxNzQxNjIsIm5iZiI6MTc1MzE3NDE2MiwiZXhwIjoxNzUzMTgxMzYyfQ.znoN-22iILXUlt6-HGYgMlmbmNZI6mjw9RjvrzgRxL0';
        //验证token
        $yztoken = Token::verify($token);
        return json(['code' => 200, 'yztoken' => $yztoken]);
    }
}

?>

四、补充:创建Token验证中间件

1、通过命令行生成中间件:php think make:middleware Auth,编辑app/middleware/Auth.php

bash 复制代码
<?php
declare (strict_types = 1);

namespace app\middleware;
use app\common\Token;
class Auth
{
    /**
     * 处理请求
     *
     * @param \think\Request $request
     * @param \Closure       $next
     * @return Response
     */
    public function handle($request, \Closure $next) {
        $token = $request->header('Authorization') ?? '';
        if (empty($token)) {
            abort(401, 'Token未提供');
        }

        try {
            $payload = Token::verify($token);
            $request->user = $payload; // 将用户信息注入请求对象
        } catch (\Exception $e) {
            abort(401, $e->getMessage());
        }
        return $next($request);
    }
}

2、应用中间件到路由

在路由文件中(如route/app.php),为需要保护的API路由添加中间件。

bash 复制代码
use app\middleware\Auth;
Route::group(function () {
    Route::get('login/login', 'login/login');
})->middleware(Auth::class);

五、关键注意事项:

1、Token存储与传递‌:客户端登录后存储Token(如localStorage:浏览器本地缓存),并在请求头中添加Authorization: Bearer 。‌

2、安全优化‌:密钥使用复杂字符串并存储在.env中;Token过期时间不宜过长;定期轮换密钥。‌

3、错误处理‌:捕获JWT异常(如过期、无效签名),返回401状态码。‌

相关推荐
BingoGo18 小时前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php
JaguarJack18 小时前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php·服务端
BingoGo2 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php
JaguarJack2 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php·服务端
JaguarJack3 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
后端·php·服务端
BingoGo3 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
php
JaguarJack4 天前
告别 Laravel 缓慢的 Blade!Livewire Blaze 来了,为你的 Laravel 性能提速
后端·php·laravel
郑州光合科技余经理4 天前
代码展示:PHP搭建海外版外卖系统源码解析
java·开发语言·前端·后端·系统架构·uni-app·php
QQ5110082854 天前
python+springboot+django/flask的校园资料分享系统
spring boot·python·django·flask·node.js·php
WeiXin_DZbishe4 天前
基于django在线音乐数据采集的设计与实现-计算机毕设 附源码 22647
javascript·spring boot·mysql·django·node.js·php·html5