Thinkphp8使用Jwt
一、宝塔切换PHP版本
安装jwt出现php版本不兼容的问题
composer require firebase/php-jwt
firebase/php-jwt依赖包要求PHP≥8.0.0,而当前Composer默认使用了PHP 7.4环境导致版本不兼容
1. 查看已安装版本
ls /www/server/php
2. 切换版本(以PHP8.3为例)
rm -f /usr/bin/php
ln -sf /www/server/php/83/bin/php /usr/bin/php
3. 验证结果
php -v # 应显示"PHP 8.3.x"
二、创建并使用JWT密钥生成命令的完整流程
1、创建自定义命令
1、生成命令文件
执行命令后会在app/command目录生成JwtKeyGenerate.php文件
php think make:command JwtKeyGenerate
2、编辑命令逻辑
修改生成的文件实现密钥生成功能
<?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中添加命令注册
'commands' => [
'jwt:keygen' => 'app\command\JwtKeyGenerate'
]
2、执行命令
运行以下命令生成密钥
php think jwt:keygen
输出示例:
三、生成token与验证token
1、在config下面创建jwt.php文件,获取生成的jwt密钥secret_key。
<?php
// config/jwt.php
return [
'secret_key' => env('JWT_SECRET', 'fallback_key'), // 必须设置默认值, // 确保这个密钥在生产环境中是安全的
'expiry' => 3600, // Token过期时间,单位秒
];
?>
2、在app/common下面创建token.php文件,封装Token生成和验证方法
<?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
<?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
<?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路由添加中间件。
use app\middleware\Auth;
Route::group(function () {
Route::get('login/login', 'login/login');
})->middleware(Auth::class);