iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 16
1

在完成所有 user 的 API 後,有一些很重要的問題需要留意,有些 method 是只有處於登入狀態,甚至還必須是 admin 的身份才能夠發送該請求。為了能夠驗證是否有使用者登入,我們可以利用 Middleware 的方式過濾掉未登入的使用者。

建立 Middleware

還記得之前在更改 create_user_table 的時候有添加一個 token 的欄位,而我們驗證登入的方式正是檢驗 Http Header 中有沒有 token 的存在。

  • 首先透過 artisan 建立自己的 middleware:

    $ php artisan make:middleware TokenAuth
    

建立完成後該 middleware 將會存在於 app/Http/Middleware 的資料夾裡頭。

  • 於 app/Http/Kernel.php 檔案裡,註冊該 middleware 於 $routeMiddleware

    protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
        'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
    
        // 註冊的 middleware
        'token.auth' => \App\Http\Middleware\TokenAuth::class
    ];
    
  • 設計 middleware 的邏輯

    此處是以比較土法煉鋼的方式驗證使用者,其實還有更快的方式( 用內建的 Auth::user(),但不知為何自己總是嘗試失敗... )

    *app/Http/Middleware/TokenAuth.php

    <?php
    
    namespace App\Http\Middleware;
    
    use Closure;
    use App\User;
    class TokenAuth
    {
        /**
         * Handle an incoming request.
         *
         * @param  \Illuminate\Http\Request  $request
         * @param  \Closure  $next
         * @return mixed
         */
        public function handle($request, Closure $next)
        {
            // 確認 Http Header 的 token 有無對應的使用者
            $api_token = request()->header('api_token');
            $auth_user = User::where('api_token', $api_token)->get();
    
            if(!count($auth_user)){
                return response(['message' => 'Authentication error']);
            }
    
            // 將通過驗證的使用者存放於 attribute 裡以便將變數傳給 controller
            $request->attributes->set('auth_user', $auth_user);
            return $next($request);
        }
    }
    

引用 middleware 於特定的 API

  • 定義權限

    以下權限的定義並非所謂的正確答案,可以視情況調整

    method admin regular user Unauthenticated user

    register|-|-|O
    login|-|-|O
    index|O|X|X
    show|O|只有自己|X
    update|只有自己|只有自己|X
    delete|O|只有自己|X

    說明:
    register 和 login 的情形不會將已登入的使用者考慮在內
    index 只有 admin 才可以查看所有使用者資料
    show、delete 除了 admin 之外,只有該資料為自己的時候請求才能夠被執行
    update 則是無論是否為 admin 都只有自己能夠更改資料

  • API routes 引用 middleware

    在 router 引用 middleware 的語法有很多種,以下取其中兩種

    *routes/api.php

    一、

    Route::post('register', 'UsersController@store');
    Route::post('login', 'UsersController@login');
    Route::get('users', 'UsersController@index')->middleware('token.auth');
    Route::get('users/{id}', 'UsersController@show')->middleware('token.auth');
    Route::put('users/{id}', 'UsersController@update')->middleware('token.auth');
    Route::delete('users/{id}', 'UsersController@destroy')->middleware('token.auth');
    

    二、

    Route::group(['middleware' => ['token.auth']], function () {
        Route::get('user', 'UsersController@index');
        Route::get('user/{id}', 'UsersController@show');
        Route::put('user/{id}', 'UsersController@update');
        Route::delete('user/{id}', 'UsersController@destroy');
    });
    
    Route::group(['middleware' => ['']], function () {
        Route::post('register', 'UsersController@store');
        Route::post('login', 'UsersController@login');
    });
    
    

實測

以 register 和 index 為例子

  • register

    不需要使用者登入 ( header 未含任何參數 ) 就可以採用的 method

    image alt

  • index

    必須經過使用者登入才可以採用 ( admin 的權限部份下一篇會解釋如何實作,此處先檢測使否登入 )

    • 未登入會出現錯誤

    image alt

    • 登入取得 api_token 存在 header 裡才能夠 request 成功

    image alt

    image alt

下一篇接續此篇主題,探討經由 middleware 過濾後的使用者後續處理。

參考資料:

  1. Middleware : https://laravel.com/docs/6.x/middleware

上一篇
Day 15 : user ( Controller -- update & destroy )
下一篇
Day 17 : 用 Middleware 管理權限 ( part II )
系列文
從零開始的Laravel RESTful api30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言