無痛重新整理jwt-token多[guard]版本

osang發表於2020-09-19
<?php

namespace App\Http\Middleware;

use Auth;
use Closure;
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
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request $request
     * @param  \Closure $next
     *
     * @throws \Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException
     *
     * @return mixed
     */
    public function handle($request, Closure $next, $role='api')
    {
        // 檢查此次請求中是否帶有 token,如果沒有則丟擲異常。 
        $this->checkForToken($request);

        // 判斷token是否在有效期內
        try {
            if (auth($role)->payload())  {
                 app('auth')->shouldUse($role);
                return $next($request);
            }
        } catch (JWTException $exception) {
            try{
                $token = auth($role)->refresh();
                // 使用一次性登入以保證此次請求的成功
                auth($role)->onceUsingId(
                    auth($role)->payload()->get('sub')
                );
                //更新請求中的token
                $request->headers->set('Authorization','Bearer '.$token);
            } catch(JWTException $exception) {
                // 如果捕獲到此異常,即代表 refresh 也過期了,使用者無法重新整理令牌,需要重新登入。
                throw new UnauthorizedHttpException('jwt-auth', $exception->getMessage());
            }
        }
        // 在響應頭中返回新的 token
        return $this->setAuthenticationHeader($next($request), $token);
    }
}

使用方式:route中介軟體中新增
'refresh.token:role'
特別注意:
1、當使用refresh.token:role中介軟體之後遇到使用者授權authorize失敗。導致非預設guard的角色操作授權失敗。
因為app.auth即AuthManager裡面使用的guard是auth中配置的預設guard。

AuthServiceProvider.php:

protected function registerAuthenticator()
    {
        $this->app->singleton('auth', function ($app) {
            $app['auth.loaded'] = true;
            return new AuthManager($app);
        });

        $this->app->singleton('auth.driver', function ($app) {
            return $app['auth']->guard();
        });
    }

AuthManager.php:

 /**
     * Get the default authentication driver name.
     *
     * @return string
     */
    public function getDefaultDriver()
    {
        return $this->app['config']['auth.defaults.guard'];
    }

這將導致我們的policy授權方法無法注入正確的user導致授權失敗。
所以在RrefreshToken中介軟體中獲取到正確的token時候,我們需要修改AuthManager的guard。避免使用者操作無法正確授權。

無痛重新整理jwt-token多[guard]版本

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章