使用 Dingo API 擴充套件包快速構建 Laravel RESTful API(九) —— API 認證實現(下)
在上篇教程中,我們介紹瞭如何通過 HTTP 基本認證和 JWT 認證實現 Dingo API 的認證,這篇教程,學院君將會給大家介紹如何在 Dingo API 中基於 OAuth 2.0 和自定義認證驅動實現 API 認證。
OAuth 2.0 認證
和Laravel Passport 一樣,Dingo API 的 OAuth 2.0 認證基於第三方擴充套件包 league/oauth2-server 實現,該擴充套件包還提供了針對 Laravel 框架的適配包 lucadegasperi/oauth2-server-laravel ,因此,在 Dingo API 中實現 OAuth 2 認證的話,直接安裝配置後面這個擴充套件包即可。但是從 Laravel 5.3 開始,由於 Laravel 官方提供的 API 認證擴充套件包 Passport 也是基於 league/oauth2-server
實現的,所以後面這個適配包就廢棄了,不僅如此,Dingo API 後續的版本也移除了 OAuth 2 驅動( Dingo\Api\Auth\Provider\OAuth2
),所以,如果你是在 Dingo API 包含 OAuth2 且 Laravel 框架版本低於 5.3 的老版本中實現 OAuth 2 認證,可以使用 lucadegasperi/oauth2-server-laravel
這個適配包快速實現,否則需要在 Dingo API 中自定義 OAuth2 驅動並自行配置 league/oauth2-server
實現 OAuth 2 認證,或者,你可以直接基於 Passport 實現 Dingo 的認證,包括上篇教程提到的 JWT 認證,也可以基於 Passport 實現(Passport 使用了另一個 JWT 擴充套件包實現基於 JWT 的 API 認證)。
在這篇教程中,為了簡化流程,我們將直接基於 Passport 實現 Dingo API 的 OAuth2 認證(5.3 之前老版本實現可以參考 Dingo 文件 ),關於 OAuth2 的底層原理,可以參考Passport 文件中的介紹,這裡我們將重點放到認證實現上。
安裝配置 Passport
如果你還沒有在專案中安裝並初始化 Passport 擴充套件包的話,可以參考Passport 官方文件進行安裝配置。這裡由於我們基於待辦任務專案進行演示,在之前的教程中已經初始化過,所以可以跳過這一步驟。
最後,記得將 config/auth.php
中的 guards.api.driver
配置值調整為 passport
以便在應用中生效:
'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'passport', 'provider' => 'users', ], ],
設定認證中介軟體
基於 Passport 認證的話,就需要修改之前設定的認證中介軟體了,開啟 Api\TaskController.php
,將定義在建構函式中的認證中介軟體調整為 auth:api
:
public function __construct() { $this->middleware('auth:api'); }
這樣一來,在認證的時候就會通過 Laravel 框架提供的中介軟體來校驗了,此外,還需要修改獲取認證使用者的程式碼:
public function index(Request $request) { $limit = $request->input('limit') ? : 10; // 獲取當前認證使用者例項 $user = $request->user(); $tasks = Task::where('user_id', $user->id)->paginate($limit); return $this->response->paginator($tasks, new TaskTransformer()); }
通過密碼授權令牌訪問認證 API
OAuth 2 提供了多種獲取授權令牌的方法,比如通過授權碼頒發訪問令牌、密碼授權令牌、隱式授權令牌、私人訪問令牌等,具體實現可以參考Passport 官方文件或者學院君寫的系列教程,這裡我們以密碼授權令牌為例做演示。
首先,我們通過如下 Artisan 命令建立一個新的需要接入 API 認證的客戶端應用:
php artisan passport:client --password
這樣一來,我們就獲取到對應的 APP ID 和 APP Secret,將其配置到 .env
中:
CLIENT_ID=7 CLIENT_SECRET=7lz6yKdRWudXgwtct6esjwEjk8DpjjFs10lMkvFh
然後我們在 routes/api.php
中定義一個用於獲取授權令牌的路由:
$api->version('v3', function ($api) { ... $api->post('user/token', function () { app('request')->validate([ 'email' => 'required|string', 'password' => 'required|string', ]); $http = new \GuzzleHttp\Client(); // 傳送相關欄位到後端應用獲取授權令牌 $response = $http->post(route('passport.token'), [ 'form_params' => [ 'grant_type' => 'password', 'client_id' => env('CLIENT_ID'), 'client_secret' => env('CLIENT_SECRET'), 'username' => app('request')->input('email'),// 這裡傳遞的是郵箱 'password' => app('request')->input('password'), // 傳遞密碼資訊 'scope' => '*' ], ]); return response()->json($response->getBody()->getContents()); }); $api->resource('tasks', \App\Http\Controllers\Api\TaskController::class); });
當我們在 Postman 中模擬訪問 user/token
時,就可以獲取到對應的訪問令牌了:
其中 access_token
就是後續訪問認證 API 時需要的令牌。還是在 Postman 中,我們將 access_token
欄位值設定到型別為 Bearer 的 Authorization 欄位,然後請求 tasks.index
路由,如果能返回相應的響應資料,表示認證成功:
至此,在 Dingo API 中基於 Passport 實現 OAuth2 認證就演示到這裡,其它型別的 OAuth2 認證請參考學院君上篇提到的教程自行去實踐。
自定義認證驅動
如果以上介紹的 HTTP 基本認證、JWT 認證以及 OAuth2 認證驅動都不能滿足你的需求,你還可以選擇在 Dingo 中自定義認證驅動。自定義認證驅動類需要實現 Dingo\Api\Contract\Auth\Provider
介面,如果認證成功,則返回對應的認證使用者例項,否則要丟擲 Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException
異常:
use Illuminate\Http\Request; use Dingo\Api\Routing\Route; use Dingo\Api\Contract\Auth\Provider; use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException; class CustomProvider implements Provider { public function authenticate(Request $request, Route $route) { // Logic to authenticate the request. throw new UnauthorizedHttpException('Unable to authenticate with supplied username and password.'); } }
如果你需要使用從 Authorization
請求頭中獲取到的令牌,和 Dingo 預設提供的 Basic
和 JWT
驅動一樣,可以選擇繼承 Dingo\Api\Auth\Provider\Authorization
基類,該基類也實現了 Dingo\Api\Contract\Auth\Provider
介面,只是新增了從 Authorization
請求頭獲取欄位值的邏輯,我們在自定義驅動中只需要實現 getAuthorizationMethod
方法來返回 Authorization
請求頭的認證型別即可:
use Illuminate\Http\Request; use Dingo\Api\Routing\Route; use Dingo\Api\Auth\Provider\Authorization; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException; class CustomProvider extends Authorization { public function authenticate(Request $request, Route $route) { $this->validateAuthorizationHeader($request); // If the authorization header passed validation we can continue to authenticate. // If authentication then fails we must throw the UnauthorizedHttpException. } public function getAuthorizationMethod() { return 'mac'; } }
定義完自定義驅動類就可以在配置檔案 config/api.php
中配置通過自定義驅動實現 Dingo API 的認證:
'auth' => [ 'custom' => 'CustomProvider', ],
或者在服務提供者的 boot
方法中擴充套件 Dingo 認證管理器驅動陣列以便在應用中可以通過自定義驅動進行 API 認證:
app(\Dingo\Api\Auth\Auth::class)->extend('custom', function ($app) { return new CustomProvider; });
關於 Dingo API 的認證實現學院君就介紹到這裡,下一篇教程我們將開始介紹 API 介面訪問頻率限制的實現。