laravel jwt 无感刷新token

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

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

<?php

namespace AppHttpMiddleware;

use Auth;
use Closure;
use TymonJWTAuthJWTAuth;
use TymonJWTAuthExceptionsJWTException;
use TymonJWTAuthHttpMiddlewareBaseMiddleware;
use TymonJWTAuthExceptionsTokenExpiredException;
use SymfonyComponentHttpKernelExceptionUnauthorizedHttpException;

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.修改AppHttpKernel.pho文件

protected $routeMiddleware = [
      //......
      'token.refresh' => AppHttpMiddlewareRefreshToken::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)
原文地址:https://www.cnblogs.com/joshua317/p/14676221.html