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状态码。‌

相关推荐
Tigshop开源商城系统19 小时前
Tigshop 开源商城系统 php v5.1.9.1版本正式发布
java·大数据·开源·php·开源软件
拾忆,想起21 小时前
超时重传 vs 快速重传:TCP双保险如何拯救网络丢包?
java·开发语言·网络·数据库·网络协议·tcp/ip·php
BingoGo21 小时前
15 个 Eloquent 高级技巧,瞬间提升你的 Laravel 应用性能
后端·php
michaelzhouh1 天前
php项目ueditor上传pdf文件,防止XSS攻击
pdf·php·xss·ueditor
合作小小程序员小小店1 天前
web网页开发,在线%商城,电商,商品购买%系统demo,基于vscode,apache,html,css,jquery,php,mysql数据库
开发语言·前端·数据库·mysql·html·php·电商
JaguarJack1 天前
15 个 Eloquent 高级技巧,瞬间提升你的 Laravel 应用性能
后端·php·laravel
拾忆,想起1 天前
TCP滑动窗口:网络世界的“智能流量阀门”
java·网络·数据库·网络协议·tcp/ip·php·哈希算法
Q_Q5110082851 天前
python+django/flask的眼科患者随访管理系统 AI智能模型
spring boot·python·django·flask·node.js·php
JavaEdge.1 天前
Cursor 2.0 扩展 Composer 功能,助力上下文感知式开发
php·composer
Q_Q5110082851 天前
python+django/flask的在线学习系统的设计与实现 积分兑换礼物
spring boot·python·django·flask·node.js·php