laravel jwt 無感刷新token


為保證和前端交互過程中,用戶可以自動刷新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)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM