首页> 实战笔录 >PHP开发笔记 >ThinkPHP ThinkPHP
TP6使用JWT实现中间件验证Token,验证用户登录信息
作者:小萝卜 2024-05-08 【 TP6 Jwt Token 】 浏览 1166
简介TP6使用JWT实现中间件验证Token,创建token解析token
开发环境和依赖
在开始之前,我们需要确保开发环境已经正确设置。以下是本文所使用的环境和依赖。请根据您的需求进行相应地更改。
PHP 7.2 或更高版本
ThinkPHP 6.0.0 或更高版本
Firebase JWT PHP 库
步骤1:安装 Firebase JWT PHP 库
composer require firebase/php-jwt
步骤2:创建Token类
为了便于管理和使用 JWT,我们创建一个名为Token的类来处理 JWT 验证的各个方面。这个类将包括创建令牌,验证令牌,获取令牌信息等功能。
在 app/common 目录下创建 Token.php 文件,并添加以下代码:
<?php
namespace app\common;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use Firebase\JWT\SignatureInvalidException;
use Firebase\JWT\ExpiredException;
use Firebase\JWT\BeforeValidException;
class Token
{
private static $key = 'testadmin'; //生成token的秘钥
private static $alg = 'HS256'; //生成token的方式
/**
* 生成token
* @param $data
* @param $expiration
* @return string
*/
public static function createToken($data, $expiration = 3600)
{
$payload = [
'iss' => 'localhost', //签发者 可以为空
'aub' => 'user_name', //面象的用户,可以为空
'sub' => 'token', //主题
'iat' => time(), //签发时间
'nbf' => time(), //在什么时候jwt开始生效
'exp' => time() + $expiration, //过期时间
'data' => $data ///这里是自已添加上去的,如果有其它信息,可以再添加数组的键值对
];
return JWT::encode($payload, self::$key, self::$alg);
}
/**
* 解析token
* @param $token
* @return \stdClass
*/
public static function decodeToken($token)
{
$status = array("code" => 500);
try {
JWT::$leeway = 60; //当前时间减去60,把时间留点余地
$decoded = JWT::decode($token, new Key(self::$key, self::$alg)); //HS256方式,这里要和签发的时候对应
$arr = (array)$decoded;
$res['code'] = 200;
$res['data'] = $arr;
return $res;
} catch (SignatureInvalidException $e) { //签名不正确
$status['msg'] = "签名不正确";
return $status;
} catch (BeforeValidException $e) { // 签名在某个时间点之后才能用
$status['msg'] = "token未生效";
return $status;
} catch (ExpiredException $e) { // token过期
$status['msg'] = "token失效";
return $status;
} catch (Exception $e) { //其他错误
$status['msg'] = "未知错误";
return $status;
}
}
/**
* 解析token返回数据部分
* @param $token
* @return false
*/
public static function getDataByToken($token)
{
$decoded = self::decodeToken($token);
return $decoded;
}
/**
* 验证token令牌是否有效
* @param $token
* @return bool
*/
public static function verifyToken($token)
{
$result = false;
try {
//$decoded = self::decodeToken($token);
$result = true;
} catch (Exception $e) {
// Invalid token
}
return $result;
}
}
步骤3:登陆时生成token
use app\common\Token;
$token_data['id'] = $adata['id'];
$token_data['gid'] = $adata['gid'];
$token = Token::createToken($token_data);
步骤4:在中间件中验证解析令牌(在/应用目录/middleware/目录下新建adminlogin.php中间件文件)
<?php
declare (strict_types = 1);
namespace app\admin\middleware;
use app\common\Token;
class AdminLogin
{
/**
* 处理请求
* 利用jwt验证token中间件
* @param \think\Request $request
* @param \Closure $next
* @return Response|\think\response\Json
*/
public function handle($request, \Closure $next)
{
$white_list = [
'/captcha.html',
'/index/login',
'/index/getcaptcha'
]; // 白名单,不用验证登录
$request_uri = $_SERVER['REQUEST_URI'];
$pathinfo = explode('?',$request_uri)[0];
$pathinfo = strtolower($pathinfo);
//排除白名单
if(!in_array($pathinfo, $white_list)) {
//验证登录
if (!$request->header('Authorization')) {
return json(['code' => 20001, 'msg' => 'token不存在']);
}
$header = $request->header('Authorization');
$token = substr($header, 7); //这里是去掉Authorization 中的 Bearer
if (Token::verifyToken($token)) {
$data = Token::getDataByToken($token);
if($data['code']==200){
$request ->admin_data = (array)$data['data']['data'];
}else{
return json(['code' => 20002, 'msg' => $data['msg']]);
}
return $next($request);
} else {
return json(['code' => 20002, 'msg' => 'token有误']);
}
}
return $next($request);
}
}
步骤5:设置路由(我这里设置的是应用中间件)
在/应用目录/middleware.php文件中新增应用中间件
<?php
// 全局中间件定义文件
return [
// 全局请求缓存
// \think\middleware\CheckRequestCache::class,
// 多语言加载
// \think\middleware\LoadLangPack::class,
// Session初始化
\think\middleware\SessionInit::class,
//登录验证
'admin_login'=>\app\admin\middleware\AdminLogin::class, //取别名
];
步骤6:在控制器中使用解析的token令牌信息
/**
* 登陆后获取管理员信息
* @return array
* @param token string
*/
public function getManager()
{
$admin_data = request()->admin_data;
$manager = new ManagerModel();
$data = $manager->field('id,admin_name,avatar,names,login_time,alogin_time')->find($admin_data['id'])->toArray();
return $this->success('获取成功',$data);
}
在控制器中,您可以通过调用reques()->admin_data来访问经过身份验证的 JWT 中存储的数据。
很赞哦! (1)