Think PHP 5 JWT实现Token生成与验证

本文详细介绍了如何使用Composer安装Lcobucci/JWT库,并展示了如何在PHP中创建和验证JWT Token,包括生成、签名验证及错误处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

composer下载安装JWT

composer require lcobucci/jwt 3.3

在extend/tools/jwt创建Token.php,在文件夹中写入

namespace tools\jwt;

use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\ValidationData;

class Token
{
    public static function createToken($uid = null)
    {
        $signer = new Sha256();//加密规则
        $time = time();//当前时间

        $token = (new Builder())
            ->issuedBy('teacher')//签发人
            ->canOnlyBeUsedBy('student')//接收人
            ->identifiedBy('MarsLei', true) //标题id
            ->issuedAt($time)//发出令牌的时间
            ->canOnlyBeUsedAfter($time) //生效时间(即时生效)
            ->expiresAt($time + 3600) //过期时间
            ->with('uid', $uid) //用户id
            ->sign($signer, 'my') //签名
            ->getToken(); //得到token
        return (string)$token;
    }

    public static function verifyToken($token = null)
    {
        //检测是否接收到了token
        if (empty($token)) {
            return 0;
        }
        //转化为可以验证的token
        $token = (new Parser())->parse((string)$token);
        //验证基本设置
        $data = new ValidationData();
        $data->setIssuer('teacher');
        $data->setAudience('student');
        $data->setId('MarsLei');

        if (!$token->validate($data)) {
            return 0;
        }
        //验证签名
        $signer = new Sha256();
        if (!$token->verify($signer, 'my')) {
            return 0;
        }
        //验证通过,返回用户id
        return $token->getClaim('uid');
    }
}
调用Token
//生成Token
$token=Token::createToken($id);
//验证Token
$res=Token::verifyToken($token);
if ($res==0){
    $this->error('Token令牌失效','test/Login/login');
}

<think>我们正在使用ThinkPHP8框架,需要集成JWT(JSONWebToken)来实现用户认证。主要步骤包括:1.安装JWT库(如firebase/php-jwt)2.封装一个用于生成验证Token的类3.创建中间件来验证请求中的Token4.配置路由中间件5.在控制器中测试注意:引用中提供的是ThinkPHP6的示例,但ThinkPHP8的中间件使用方式类似,但部分细节可能不同(例如中间件的定义和注册)。###步骤1:安装JWT库使用Composer安装`firebase/php-jwt`库:```bashcomposerrequirefirebase/php-jwt```###步骤2:封装Token工具类创建一个工具类来处理Token生成验证。例如,在`app/common`目录下创建`Token.php`(如果没有common目录,可以创建)。```php<?phpnamespaceapp\common;useFirebase\JWT\JWT;useFirebase\JWT\Key;usethink\facade\Config;classToken{//生成TokenpublicstaticfunctiongenerateToken($uid){$key=Config::get('jwt.key');//从配置中获取密钥$time=time();$token=['iss'=>Config::get('jwt.iss'),//签发者'aud'=>Config::get('jwt.aud'),//接收方'iat'=>$time,//签发时间'nbf'=>$time,//生效时间'exp'=>$time+Config::get('jwt.expire'),//过期时间'data'=>[//自定义数据'uid'=>$uid]];returnJWT::encode($token,$key,Config::get('jwt.alg'));}//验证TokenpublicstaticfunctionverifyToken($token){$key=Config::get('jwt.key');$alg=Config::get('jwt.alg');try{$decoded=JWT::decode($token,newKey($key,$alg));return['code'=>200,'data'=>(array)$decoded];}catch(\Exception$e){return['code'=>401,'msg'=>$e->getMessage()];}}}```在配置文件`config/jwt.php`中设置JWT参数(如果没有该文件,请创建):```php<?phpreturn['key'=>'your-secret-key',//密钥,建议使用长随机字符串'alg'=>'HS256',//加密算法,如HS256'iss'=>'your-issuer',//签发者'aud'=>'your-audience',//接收方'expire'=>7200,//过期时间(秒)];```###步骤3:创建中间件验证Token在`app/middleware`目录下创建`CheckToken.php`中间件:```php<?phpnamespaceapp\middleware;useapp\common\Token;usethink\facade\Request;usethink\Response;classCheckToken{publicfunctionhandle($request,\Closure$next){//从请求头中获取token,例如:Authorization:Bearer{token}$authHeader=Request::header('Authorization');if(empty($authHeader)){returnjson(['code'=>401,'msg'=>'Token缺失']);}//验证BearerToken格式if(preg_match('/Bearer\s+(\S+)/',$authHeader,$matches)){$token=$matches[1];}else{returnjson(['code'=>401,'msg'=>'Token格式错误']);}$result=Token::verifyToken($token);if($result['code']!=200){returnjson(['code'=>401,'msg'=>'Token无效或已过期','error'=>$result['msg']]);}//将解析出的用户数据传递给请求$request->userInfo=$result['data'];return$next($request);}}```###步骤4:配置路由中间件在`app/middleware.php`文件中注册中间件:```php<?phpreturn[//...其他中间件\app\middleware\CheckToken::class,];```然后,在需要验证Token的路由中应用中间件。例如,在路由文件`route/app.php`中:```phpusethink\facade\Route;//不需要Token验证的路由Route::post('login','index/Login/login');//需要Token验证的路由组Route::group(function(){Route::get('user/info','index/User/info');})->middleware(\app\middleware\CheckToken::class);```###步骤5:测试在控制器中编写登录方法生成Token,以及需要验证Token的方法。登录控制器示例(`app/controller/Login.php`):```php<?phpnamespaceapp\controller;useapp\common\Token;usethink\facade\Request;classLogin{publicfunctionlogin(){$data=Request::post();//假设验证用户身份成功后,获取用户ID$uid=1;//实际从数据库验证获取$token=Token::generateToken($uid);returnjson(['code'=>200,'token'=>$token]);}}```用户信息控制器(`app/controller/User.php`):```php<?phpnamespaceapp\controller;usethink\facade\Request;classUser{publicfunctioninfo(){//通过中间件,我们可以从请求中获取用户信息$userInfo=Request::userInfo;returnjson(['code'=>200,'data'=>$userInfo]);}}```###注意事项1.密钥(key)要足够复杂,且不要泄露。2.根据实际情况调整Token的过期时间(expire)。3.在中间件中,我们使用`Authorization`头传递Token,这是常见的做法。4.异常处理:在验证Token时,JWT库会抛出异常,我们捕获后返回相应的错误信息。###测试方法可以使用Postman测试:-登录接口:POST请求,获取Token。-用户信息接口:GET请求,在请求头中添加`Authorization:Bearer<token>`。###相关问题1.如何设置Token刷新机制?2.如何处理Token被盗用的情况?3.在分布式系统中,如何保证JWT的有效性?</think>在 ThinkPHP 8 中集成 JWT 生成验证 Token 的完整步骤如下: ### 1. 安装 JWT 库 ```bash composer require firebase/php-jwt ``` ### 2. 封装 Token 工具类 在 `app/common` 目录创建 `Token.php`: ```php <?php namespace app\common; use Firebase\JWT\JWT; use Firebase\JWT\Key; use think\facade\Config; class Token { // 生成Token public static function generate($uid) { $key = Config::get('jwt.key'); // 从配置获取密钥 $payload = [ 'iss' => 'your-issuer', // 签发者 'aud' => 'your-audience', // 接收方 'iat' => time(), // 签发时间 'nbf' => time(), // 生效时间 'exp' => time() + 7200, // 过期时间(2小时) 'data' => [ // 自定义数据 'uid' => $uid ] ]; return JWT::encode($payload, $key, 'HS256'); } // 验证Token public static function verify($token) { $key = Config::get('jwt.key'); try { $decoded = JWT::decode($token, new Key($key, 'HS256')); return ['code' => 200, 'data' => (array)$decoded]; } catch (\Exception $e) { return ['code' => 401, 'msg' => $e->getMessage()]; } } } ``` ### 3. 创建配置文件 在 `config/jwt.php` 添加: ```php <?php return [ 'key' => 'your-secret-key' // 替换为强密码(32位以上) ]; ``` ### 4. 创建验证中间件 在 `app/middleware` 创建 `JwtAuth.php`: ```php <?php namespace app\middleware; use app\common\Token; use think\facade\Request; class JwtAuth { public function handle($request, \Closure $next) { $token = Request::header('Authorization'); if (!$token) { return json(['code' => 401, 'msg' => 'Token缺失']); } // 移除Bearer前缀 if (str_starts_with($token, 'Bearer ')) { $token = substr($token, 7); } $result = Token::verify($token); if ($result['code'] !== 200) { return json(['code' => 401, 'msg' => 'Token无效: '.$result['msg']]); } // 将用户信息附加到请求对象 $request->user = $result['data']->data; return $next($request); } } ``` ### 5. 注册中间件 在 `app/middleware.php` 添加: ```php return [ // ...其他中间件 'jwt' => \app\middleware\JwtAuth::class ]; ``` ### 6. 控制器中使用 **登录生成 Token** (`app/controller/Auth.php`): ```php public function login() { // 验证用户逻辑... $uid = 1001; // 获取实际用户ID $token = \app\common\Token::generate($uid); return json([ 'code' => 200, 'token' => $token, 'expire' => time() + 7200 ]); } ``` **受保护路由** (`app/controller/User.php`): ```php public function profile() { // 通过中间件获取用户信息 $uid = request()->user->uid; return json(['code' => 200, 'data' => ['uid' => $uid]]); } ``` ### 7. 路由配置 (`route/app.php`) ```php // 登录路由(不需要Token) Route::post('login', 'Auth/login'); // 需要验证的路由组 Route::group(function () { Route::get('profile', 'User/profile'); })->middleware('jwt'); ``` ### 8. 测试方式 1. **获取Token**: ```http POST /login Content-Type: application/json {"username":"test","password":"123456"} ``` 2. **访问受保护路由**: ```http GET /profile Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9... ``` ### 关键注意事项 1. **密钥安全**:`jwt.key` 必须使用强密码(建议32位随机字符串) 2. **Token传输**:通过 `Authorization: Bearer <token>` 头传递 3. **错误处理**:中间件返回标准HTTP 401状态码 4. **有效期**:根据业务需求调整 `exp` 过期时间 5. **HTTPS**:生产环境必须启用HTTPS保证Token安全 ### 常见问题解决 - **Token过期**:捕获 `ExpiredException` 实现刷新机制 - **无效Token**:检查密钥一致性和传输格式 - **跨域问题**:确保响应头包含 `Access-Control-Allow-Headers: Authorization` > 实际应用时建议将用户关键信息(如权限角色)加入Token payload,但避免存储敏感数据[^3][^4]。 --- ### 相关问题 1. 如何实现JWT Token的自动刷新机制? 2. 在分布式系统中如何保证JWT的有效性? 3. 如何处理JWT Token被盗用的情况? 4. ThinkPHP8中间件和TP6在使用上有哪些主要区别? 5. 除了Authorization头,还有哪些安全的Token传输方式?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值