zoukankan      html  css  js  c++  java
  • 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)
  • 相关阅读:
    使用php语言生成二维码
    简单的二级目录 操作
    上传图片 以及做成缩略图
    第一天 :学习node.js
    中文api接口
    PHP中获取当前页面的完整URL
    tp中session用来做权限方法 (缓解mysql压力)
    时间倒计时
    static关键字
    Windows程序内部运行原理简介
  • 原文地址:https://www.cnblogs.com/joshua317/p/14676221.html
Copyright © 2011-2022 走看看