调用博主最近登录时间
生活中的HYGGE
laravel jwt 无感刷新token
PHP

laravel jwt 无感刷新token

hygge
2024-05-04 / 0 评论 / 18 阅读 / 正在检测是否收录...

为保证和前端交互过程中,用户可以自动刷新token

  1. 创建一个中间件文件,命名为 RefreshToken

    <?php
    
    namespace App\Http\Middleware;
    
    use Auth;
    use Closure;
    use Tymon\JWTAuth\JWTAuth;
    use Tymon\JWTAuth\Exceptions\JWTException;
    use Tymon\JWTAuth\Http\Middleware\BaseMiddleware;
    use Tymon\JWTAuth\Exceptions\TokenExpiredException;
    use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
    
    class RefreshToken extends BaseMiddleware
    {
     function handle($request, Closure $next)
     {
         // 检查此次请求中是否带有 token,如果没有则抛出异常。
         $this->checkForToken($request);
    
         // 使用 try 包裹,以捕捉 token 过期所抛出的 TokenExpiredException  异常
         try {
             // 检测用户的登录状态,如果正常则通过
             if ($this->auth->parseToken()->authenticate()) {
                 return $next($request);
             }
             throw new UnauthorizedHttpException('jwt-auth', '未登录');
         } catch (TokenExpiredException $exception) {
             // 此处捕获到了 token 过期所抛出的 TokenExpiredException 异常,我们在这里需要做的是刷新该用户的 token 并将它添加到响应头中
             try {
                 /*
                  * token在刷新期内,是可以自动执行刷新获取新的token的
                  * 当JWT_BLACKLIST_ENABLED=false时,可以在JWT_REFRESH_TTL时间内,无限次刷新使用旧的token换取新的token
                  * 当JWT_BLACKLIST_ENABLED=true时,刷新token后旧的token即刻失效,被放入黑名单
                  * */
                 // 刷新用户的 token
                 $token = $this->auth->refresh();
                 // 使用一次性登录以保证此次请求的成功
                 Auth::guard('api')->onceUsingId($this->auth->manager()->getPayloadFactory()->buildClaimsCollection()->toPlainArray()['sub']);
             } catch (JWTException $exception) {
                 // 如果捕获到此异常,即代表 refresh 也过期了,用户无法刷新令牌,需要重新登录。
                 throw new UnauthorizedHttpException('jwt-auth', $exception->getMessage());
             }
         }
         // 在响应头中返回新的 token
         return $this->setAuthenticationHeader($next($request), $token);
     }
    }
  2. 修改App\Http\Kernel.pho文件

    protected $routeMiddleware = [
       //......
       'token.refresh' => \App\Http\Middleware\RefreshToken::class,
       //......
    ];
  3. 修改routes.api.php文件

    // 需要 token 验证的接口
         $api->group(['middleware' => ['token.refresh','auth.jwt']], function($api) {
    //.......
    });
  4. 修改.env文件

    #Jwt
    JWT_SECRET=HSKxIUfwCdJj5gadbqfQo5im9zje95g9
    #token有效时间,单位:分钟, 有效时间调整为2个小时
    JWT_TTL=120
    #为了使令牌无效,您必须启用黑名单。如果不想或不需要此功能,请将其设置为 false。
    #当JWT_BLACKLIST_ENABLED=false时,可以在JWT_REFRESH_TTL时间内,无限次刷新使用旧的token换取新的token
    #当JWT_BLACKLIST_ENABLED=true时,刷新token后旧的token即刻失效,被放入黑名单
    JWT_BLACKLIST_ENABLED=true
    
    #当多个并发请求使用相同的JWT进行时,由于 access_token 的刷新 ,其中一些可能会失败,以秒为单位设置请求时间以防止并发的请求失败。
    #时间为10分钟,10分钟之内可以拿旧的token换取新的token。当JWT_BLACKLIST_ENABLED为true时,可以保证不会立即让token失效
    JWT_BLACKLIST_GRACE_PERIOD=600

5.备注:

JWT token的三个时间,config/jwt.php查看
a.有效时间,有效是指你获取token后,在多少时间内可以凭这个token去获取资源,逾期无效。

'ttl' => env('JWT_TTL', 60), //单位分钟

b.刷新时间,刷新时间指的是在这个时间内可以凭旧 token 换取一个新 token。例如 token 有效时间为 60 分钟,刷新时间为 20160 分钟,在 60 分钟内可以通过这个 token 获取新 token,但是超过 60 分钟是不可以的,然后你可以一直循环获取,直到总时间超过 20160 分钟,不能再获取。
这里要强调的是,是否在刷新期可以一直用旧的token获取新的token,这个是由blacklist_enabled这个配置决定的,这个是指是否开启黑名单,默认是开启的,即刷新后,旧token立马加入黑名单,不可在用。

'refresh_ttl' => env('JWT_REFRESH_TTL', 20160),

c.宽限时间,宽限时间是为了解决并发请求的问题,假如宽限时间为 0s ,那么在新旧 token 交接的时候,并发请求就会出错,所以需要设定一个宽限时间,在宽限时间内,旧 token 仍然能够正常使用

// 宽限时间需要开启黑名单(默认是开启的),黑名单保证过期token不可再用
'blacklist_enabled' => env('JWT_BLACKLIST_ENABLED', true)

// 设定宽限时间,单位:秒
'blacklist_grace_period' => env('JWT_BLACKLIST_GRACE_PERIOD', 600)
0

评论 (0)

取消