thinkphp firebase/jwt-token, refresh_token使用
但是如何实现通过refreshToken刷新token呢?
首先,refreshToken有效时间一定要比token有效时间长至少才能不影响用户体验,具体要长多少得以实际需求为准,建议是24小时
前端每次访问后端都携带token,如果token失效则后端直接返回类似token失效请重新登录的报文。
前端第一次收到token失效的响应后,从本地存储拿refreshToken再去请求
后端一检测到refreshToken参数不为空,就去校验解析这个refreshToken
如果有效,后端就返回一个新的token及refreshToken给前端,前端收到后更新本地存储,同时拿这个新的token向后端发起第三次请求,然后成功获取资源
如果无效,则后端同样返回token失效,前端第二次收到失效的响应则跳转到登录页重新登录 ————————————————
版权声明:本文为CSDN博主「isFuong」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/isFuong/article/details/114946766
<?php
/**
* Created by PhpStorm.
* User: wangkxin@foxmail.com
* Date: 2022/9/7
* Time: 17:48
*/
namespace app\api\controller;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
class Token
{
/**
* 生成token
*/
public function getToken()
{
$key = 'suka2'; // key
$time = time(); // 当前时间
$token = [
'iss' => 'http://www.buddha.com', // 签发者 可选
'aud' => 'http://www.buddha.com', // 接收该JWT的一方,可选
'iat' => $time, // 签发时间
'nbf' => $time , // (Not Before):某个时间点后才能访问,比如设置time+30,表示当前时间30秒后才能使用
'exp' => $time + 7200, // 过期时间,这里设置2个小时
'data' => [ // 自定义信息,不要定义敏感信息
'id' => 1,
'username' => 'buddha'
]
];
$token = JWT::encode($token, $key,"HS256"); // 输出Token
return json(['status'=>200,'data'=>$token]);
}
/**
* 验证token
*/
public function verification()
{
$key = 'suka2'; // key要和签发的时候一样
$jwt = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vd3d3LmJ1ZGRoYS5jb20iLCJhdWQiOiJodHRwOi8vd3d3LmJ1ZGRoYS5jb20iLCJpYXQiOjE2NjI2MTkyODQsIm5iZiI6MTY2MjYxOTI4NCwiZXhwIjoxNjYyNjI2NDg0LCJkYXRhIjp7ImlkIjoxLCJ1c2VybmFtZSI6ImJ1ZGRoYSJ9fQ.GHnf0MyA8FHOqajNBhv56VFJTxFo0UKtb3gDocvR0dY"; // 签发的Token
try {
JWT::$leeway = 60; // 当前时间减去60,把时间留点余地
$decoded = JWT::decode($jwt, new Key($key, 'HS256')); // HS256方式,这里要和签发的时候对应
$arr = (array)$decoded;
return json(['data'=>$arr]);
} catch(\Firebase\JWT\SignatureInvalidException $e) { // 签名不正确
echo $e->getMessage();
}catch(\Firebase\JWT\BeforeValidException $e) { // 签名在某个时间点之后才能用
echo $e->getMessage();
}catch(\Firebase\JWT\ExpiredException $e) { // token过期
echo $e->getMessage();
}catch(\Exception $e) { // 其他错误
echo $e->getMessage();
}
// Firebase定义了多个throw new,我们可以捕获多个catch来定义问题,catch加入自己的业务
// 比如token过期可以用当前Token刷新一个新Token
}
/**
* 使用refresh token换取新的token
*/
public function getNewToken()
{
$key = 'suka2'; // key要和签发的时候一样
$jwt = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vd3d3LmJ1ZGRoYS5jb20iLCJpYXQiOjE2NjI2MTc0NjEsImRhdGEiOnsiaWQiOjEsInVzZXJuYW1lIjoiYnVkZGhhIn0sInNjb3BlcyI6InJvbGVfYWNjZXNzIiwiZXhwIjoxNjYyNjI0NjYxfQ.Tls7kDGbj_NXpl4fzGm_EfTFFSy29myMJC9I4H10nVM"; // 签发的Token
try {
JWT::$leeway = 60; // 当前时间减去60,把时间留点余地
$decoded = JWT::decode($jwt, new Key($key, 'HS256')); // HS256方式,这里要和签发的时候对应
$arr = (array)$decoded;
$data = $arr['data'];
$new_token = self::getToken();
return $new_token;
} catch(\Firebase\JWT\SignatureInvalidException $e) { // 签名不正确
echo $e->getMessage();
}catch(\Firebase\JWT\BeforeValidException $e) { // 签名在某个时间点之后才能用
echo $e->getMessage();
}catch(\Firebase\JWT\ExpiredException $e) { // token过期
echo $e->getMessage();
}catch(\Exception $e) { // 其他错误
echo $e->getMessage();
}
}
/**
* 同时生成token和refresh_token
*/
public function authorizations()
{
$key = 'suka2'; // key
$time = time(); // 当前时间
// 自定义信息
$token = [
'iss' => 'http://www.buddha.com', // 签发者 可选
'iat' => $time, // 签发时间
'data' => [ // 自定义信息,不要定义敏感信息
'id' => 1,
'username' => 'buddha'
]
];
$access_token = $token;
$access_token['scopes'] = 'role_access'; // token标识,请求接口的token
$access_token['exp'] = $time + 7200; // access_token过期时间,这里设置2个小时
$refresh_token = $token;
$refresh_token['scopes'] = 'role_refresh'; // token标识,刷新access_token
$refresh_token['exp'] = $time + (86400 * 30); // access_token过期时间,这里设置30天
$jsonList = [
'access_token' => JWT::encode($access_token, $key,"HS256"),
'refresh_token' => JWT::encode($refresh_token, $key,"HS256"),
'token_type' => 'bearer' // token_type:表示令牌类型,该值大小写不敏感,这里用bearer
];
header("HTTP/1.1 201 Created");
return json(['status'=>200,'data'=>$jsonList]); // 返回给客户端token信息
}
}