Laravel 經過 Passport 實現 API 請求認證:令牌做用域詳解

配置後端應用

在後端應用 blog 中經過 Passport::tokensCan 定義 API 認證的令牌做用域。打開 AuthServiceProvider 服務提供者類,在 boot 方法中調用該方法,設置三個令牌做用域:php

// 令牌做用域
Passport::tokensCan([
    'basic-user-info' => '獲取用戶名、郵箱信息',
    'all-user-info' => '獲取用戶全部信息',
    'get-post-info' => '獲取文章詳細信息',
]);

打開 app/Http/Kernel.php,在 $routeMiddleware 屬性中引入兩個中間件:後端

'scopes' => \Laravel\Passport\Http\Middleware\CheckScopes::class,
'scope' => \Laravel\Passport\Http\Middleware\CheckForAnyScope::class,

scopes 用於檢查傳入令牌做用域是否包含全部指定中間件參數,scope 用於檢查傳入令牌做用域是否包含任意指定中間件參數。api

routes/api.php 中新增一個獲取文章詳情信息的路由,並修改路由定義以下:瀏覽器

Route::middleware('auth:api')->group(function () {
    Route::get('/user', function (Request $request) {
        $user = $request->user();
        if ($user->tokenCan('all-user-info')) {
            // 若是用戶令牌有獲取全部信息權限,返回全部用戶字段
            return $user;
        }
        // 不然返回用戶名和郵箱等基本信息
        return ['name' => $user->name, 'email' => $user->email];
    })->middleware('scope:basic-user-info,all-user-info');
    
    Route::get('/post/{id}', function (Request $request, $id) {
        return \App\Post::find($id);
    })->middleware('scopes:get-post-info');
});

第一個路由應用了 scope 中間件,要求傳入令牌做用域包含 basic-user-infoall-user-info 任意一個便可,而且在路由閉包中根據用戶具體字段獲取權限進一步進行了細分;安全

第二個路由應用了 scopes 中間件,要求傳入令牌做用域必須包含 get-post-info,若是有多個的話,能夠經過逗號分隔。閉包

在第三方應用中測試

在第三方應用 testapp,將配置信息修改回受權碼令牌對應配置,而後在 /auth 路由對應控制器方法 LoginController@oauth 中,設置 scope 請求字段值:app

public function oauth()
{
    $query = http_build_query([
        'client_id' => config('services.blog.appid'),
        'redirect_uri' => config('services.blog.callback'),
        'response_type' => 'code',
        'scope' => 'all-user-info get-post-info',
    ]);

    return redirect('http://blog.test/oauth/authorize?'.$query);
}
在本例中,爲了簡化處理流程,直接在第三方應用控制器方法中寫死了做用域,實際場景中可讓用戶自行勾選,而後經過表單傳遞到控制器方法。

在瀏覽器中訪問 http://test.app/auth 經過受權碼獲取令牌,跳轉到後端系統受權界面時會多出一段提示信息告知該受權令牌的做用域。ide

點擊綠色的確認受權按鈕後,就可在第三方應用中獲取到受權令牌,與此同時,也會在後端應用數據表 oauth_access_tokensoauth_auth_codes 生成的記錄看到對應的 scopes 字段值。post

接下來,能夠經過取得的 access_token 在 Postman 中測試對後端認證接口的訪問。測試

請求 /api/user/api/post/1 都成功了。


把第三方應用 /auth 路由傳遞的 scope 請求字段值調整爲了 basic-user-info

public function oauth()
{

    $query = http_build_query([
        'client_id' => config('services.blog.appid'),
        'redirect_uri' => config('services.blog.callback'),
        'response_type' => 'code',
        'scope' => 'basic-user-info',
    ]);

    return redirect('http://blog.test/oauth/authorize?'.$query);
}

再次經過 http://test.app/auth 獲取令牌,令牌做用域就會發生變化。

確認受權以後,會獲取到新的令牌信息,而後使用這個令牌訪問用戶接口,就只能取到最基本的用戶字段信息,試圖訪問文章詳情接口,則會返回 403 響應。

結語

一般會在 scope 字段傳入 * (或留空,每種令牌認證有所不一樣)表示獲取到的令牌具有全部認證接口訪問權限,但若是對安全性要求比較高的系統,則能夠經過令牌做用域的方式對令牌訪問權限作更細分的設置,經過 Passport 內置的腳手架,能夠快速實現令牌做用域功能,很是方便。

相關文章
相關標籤/搜索