延續 Lumen – Laravel 微型框架使用 JWT 這篇筆記,加上自動更新 Token,從 Laravel – JWT 自動更新 Token 改成適合 Lumen 使用的 JWT 自動更新 Token。
新增 jwtRefresh Middle
php artisan make:middleware jwtRefresh
<?php
namespace App\Http\Middleware;
use Closure;
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 Illuminate\Contracts\Auth\Factory as Auth;
class JwtRefreshToken extends BaseMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
try {
//檢查是否有使用者通過驗證
$user = $this->auth->parseToken()->authenticate();
// //Token TTL 到期時間
// $expireTime = JWTAuth::payload()['exp'];
// // 如果 Token 到期時間小於5分鐘,重新產生一個新的 Token 並附帶在 header 送出,讓前端重新抓取.
// if (($expireTime - time()) < 5*60 && ($expireTime - time()) > 0) {
// $refreshed = JWTAuth::refresh(JWTAuth::getToken());
// $user = JWTAuth::setToken($refreshed)->toUser();
// $request->headers->set('Authorization', 'Bearer '.$refreshed);
// // 輸出到BODY測試
// return response()->json([
// 'code' => 200,
// 'user' => $user,
// 'access_token' => $refreshed,
// 'token_type' => 'bearer',
// 'expires_in' => JWTAuth::factory()->getTTL(),
// ]);
// }
} catch (Exception $e) {
//檢查 Token 是否無效
if ($e instanceof TokenInvalidException){
$status = 401;
$message = 'This token is invalid. Please Login';
return response()->json(compact('status','message'),401);
//檢查 Token 是否到期
}else if ($e instanceof TokenExpiredException){
try
{
// 如果 Token 到期,重新產生一個新的 Token 並附帶在 header 送出,讓前端重新抓取.
$refreshed = $this->auth->refresh($this->auth->getToken());
$user = $this->auth->setToken($refreshed)->toUser();
$request->headers->set('Authorization','Bearer '.$refreshed);
//輸出到BODY測試
//return response()->json([
// 'code' => 200,
// 'user' => $user,
// 'access_token' => $refreshed,
// 'token_type' => 'bearer',
// 'expires_in' => $this->auth->factory()->getTTL(),
//]);
}catch (JWTException $e){
// Token 無法被 refresh
return response()->json([
'code' => 103,
'message' => 'Token cannot be refreshed, please Login again'
]);
}
}else{
//找不到 Token.
$message = 'Authorization Token not found';
return response()->json(compact('message'), 404);
}
}
return $next($request);
}
}
修改 bootstrap\app.php 註冊 jwtRefresh Middleware
$app->routeMiddleware([
'auth' => App\Http\Middleware\Authenticate::class,
//Jwt Token Auto Refresh Middleware
'jwtRefresh' => App\Http\Middleware\JwtRefreshToken::class,
]);
修改 UserLoginController
public function __construct()
{
//除了 login 其餘 function 都要經過 api 的 middleware 檢查
$this->middleware('auth:api', ['except' => ['login']]);
//除了 login 其餘 function 都要經過 jwtRefresh 的 middleware 檢查 token
$this->middleware('jwtRefresh', ['except' => ['login']]);
}
修改 Authenticate Middleware (Auth)
public function handle($request, Closure $next, $guard = null)
{
// 將使用者判斷註解關閉或移除
// if ($this->auth->guard($guard)->guest()) {
// return response('Unauthorized.', 401);
// }
return $next($request);
}
成品同步放在我的 GitHub 上