之前寫了一個 JWT 自動更新 筆記,現在實作在公司的 API 時候,發現出現 500 錯誤訊息,也就是說在檢驗 JWT Token 的時候,有些錯誤並沒有做相對應的處理及回應。

修改 app\Http\Middleware\JwtRefreshToken.php

在開頭的時候先檢查 Header 裡面有沒有帶入 Token 資料,然後檢查該 Token 是否符合 Bearer 類別,最後檢查該 Token 是否是某個使用者登入使用。

由於採用自動更新 Token 方式,也就是說當 Token 到期時間剩下三分鐘時,會自動更新 Token 並附加到 Header 中,若使用者剛好在這三分鐘都沒跟 API 連線,則該 Token 就會進入到過期的 Exception ,這時候會拋出 Token 過期訊息請前端重新登入。

<?php

namespace App\Http\Middleware;

use Closure;
use JWTAuth;
use Exception;
use Tymon\JWTAuth\Http\Middleware\BaseMiddleware;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Exceptions\TokenInvalidException as TokenInvalidException;
use Tymon\JWTAuth\Exceptions\TokenExpiredException as TokenExpiredException;
use Auth;
use App\Traits\ApiResponser;

class JwtRefreshToken extends BaseMiddleware
{
    use ApiResponser;

    public function handle($request, Closure $next){
        //從header找授權資料
        $authorization = $request->header('authorization');
        //缺少授權資料
        if(empty($authorization)){
            return $this->errorResponse('Authorization required.', 400);
        }
        $chk = explode(' ',$authorization);
        //授權格式錯誤缺少 "Bearer "
        if($chk[0] != 'Bearer'){
            return $this->errorResponse('Authorization format error.', 416);
        }
        try {
            //檢查是否有使用者通過驗證
            if(JWTAuth::parseToken()->authenticate()){
                //Token TTL 到期時間
                $expireTime = JWTAuth::payload()['exp'];
                // 如果 Token 到期時間小於3分鐘,重新產生一個新的 Token 並附帶在 header 送出,讓前端重新抓取.
                if (($expireTime - time()) < 3*60 && ($expireTime - time()) > 0) {
                    $refreshed = JWTAuth::refresh(JWTAuth::getToken());
                    $user = JWTAuth::setToken($refreshed)->toUser();
                    $request->headers->set('Authorization', 'Bearer '.$refreshed);
                }
            }else{
                return $this->errorResponse('This token is not match the user.', 404);
            }
        } catch (Exception $e) {
            if ($e instanceof TokenInvalidException){ //檢查 Token 是否無效
                return $this->errorResponse('This token is invalid. Please Login.', 401);
            }else if ($e instanceof TokenExpiredException){ //檢查 Token 是否到期
                return $this->errorResponse('This token is expired. Please Login.', 400);
            }else{ //找不到 Token.
                return $this->errorResponse('Authorization Token not found. Please Login.', 404);
            }
        }
        return $next($request);
    }
}

最後修改日期: 2021 年 5 月 23 日