tp8.0\jwt接口安全验证

环境:php8.3\tp8.1\firebase-jwt6.1

app\middleware\JwtAuth

php 复制代码
<?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;

php 复制代码
<?php

namespace 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 {
            // 生成JWT
            return 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 {
            // 解码JWT
            return 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

php 复制代码
<?php

namespace 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头中的Token

        if (!$token) {
            return json(['code' => 401, 'message' => 'Token not provided'], 401);
        }

        // 解码Token
        try {
            $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]);
    }
}

这是完整的步骤,欢迎大家指正。

相关推荐
Nan_Shu_6141 小时前
学习:uniapp全栈微信小程序vue3后台-额外/精彩报错篇
前端·学习·微信小程序·小程序·uni-app·notepad++
excel2 小时前
Vue3 中的双向链表依赖管理详解与示例
前端
lypzcgf3 小时前
Coze源码分析-资源库-编辑插件-后端源码-安全与错误处理
安全·插件·coze·coze源码分析·智能体平台·ai应用平台·agent平台
前端小白从0开始3 小时前
Chrome DevTools高级用法:性能面板内存泄漏排查
前端·chrome·chrome devtools
EveryPossible3 小时前
带有渐变光晕
前端·javascript·css
粟悟饭&龟波功3 小时前
【网络安全】一、入门篇:读懂 HTTP 协议
安全·web安全·http
jojo是只猫3 小时前
Vue 3 开发的 HLS 视频流播放组件+异常处理
前端·javascript·vue.js
卓码软件测评3 小时前
第三方软件登记测试机构:【软件登记测试机构HTML5测试技术】
前端·功能测试·测试工具·html·测试用例·html5
CS Beginner3 小时前
【html】canvas实现一个时钟
前端·html
骥龙3 小时前
粤港澳全运会网络安全防御体系深度解析:威胁态势与实战防护
网络·安全·web安全