Passport OAuth 認證
Laravel Passport
介紹
在 Laravel 中,實作基於傳統表單的登陸和授權已經非常簡單,但是如何滿足 API 場景下的授權需求呢?在 API 場景裡通常透過令牌來實現使用者授權,而非維護請求之間的 Session 狀態。在 Laravel 專案中使用 Passport 可以輕鬆實現 API 授權認證,Passport 可以在幾分鐘之內為您的應用程式提供完整的 OAuth2 服務端實作。 Passport 是基於由 Andy Millington 和 Simon Hamp 維護的 League OAuth2 server 建立的。
{note} 本文檔假設你已熟悉 OAuth2 。如果你並不了解 OAuth2 ,閱讀之前請先熟悉下 OAuth2 的 常用術語 和特性。
安裝
#在開始之前,請透過Composer 套件管理器安裝Passport:
composer require laravel/passport
Passport 服務提供者使用框架註冊自己的資料庫遷移目錄,因此在註冊提供器後,就應該執行Passport 的遷移命令來自動建立儲存客戶端和令牌的資料表:
php artisan migrate
接下來,執行passport:install
指令來建立產生安全存取權杖時所需的加密金鑰,同時,這條指令也會建立用於產生存取權杖的「個人存取」客戶端和「密碼授權」客戶端:
php artisan passport:install
上面命令執行後,請將Laravel\Passport\HasApiTokens
Trait 加入到App\User
模型中,這個Trait 會為你的模型提供一些輔助函數,用於檢查已認證使用者的令牌和使用範圍:
<?php namespace App; use Laravel\Passport\HasApiTokens; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable{ use HasApiTokens, Notifiable; }
接下來,在AuthServiceProvider
的boot
#方法中呼叫Passport::routes
函數。這個函數會註冊發出存取令牌並撤銷存取令牌、客戶端和個人存取令牌所必需的路由:
<?php namespace App\Providers; use Laravel\Passport\Passport; use Illuminate\Support\Facades\Gate; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; class AuthServiceProvider extends ServiceProvider{ /** * 应用程序的策略映射。 * * @var array */ protected $policies = [ 'App\Model' => 'App\Policies\ModelPolicy', ]; /** * 注册任何认证/授权服务。 * * @return void */ public function boot() { $this->registerPolicies(); Passport::routes(); } }
最後,將設定檔config/auth.php
中授權看守器guards
的api
的driver
選項改為passport
。此調整會讓你的應用程式在驗證傳入的API 的請求時使用Passport 的TokenGuard
來處理:
'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'passport', 'provider' => 'users', ], ],
自訂遷移
#如果你不打算使用Passport 的預設遷移,你應該在AppServiceProvider
的register
方法中呼叫Passport::ignoreMigrations
方法。你可以用這個指令 php artisan vendor:publish --tag=passport-migrations
匯出預設遷移。
預設情況下,Passport 使用欄位 “user_id”標識使用者。如果想要使用不同的欄位標識使用者 (例如:uuid),可以修改預設的 Passport 遷移檔案。
前端快速上手
{note} 為了使用 Passport 的 Vue 元件,你必須使用 Vue JavaScript 框架。這些元件也使用了 Bootstrap CSS 框架。然而,如果你不打算使用這些工具,這些元件對於你自己的前端元件編寫也十分有價值。
Passport 提供了一系列 JSON API ,你可以用它們來允許你的使用者建立客戶端和個人存取權杖。然而,編寫與這些 API 互動的前端程式碼可能是很佔用時間的。因此,Passport 也包含了預先編譯的 Vue 元件,你可以直接使用或將其作為你自己的前端參考。
要使用Passport 的Vue 元件,使用vendor:publish
Artisan 指令:
php artisan vendor:publish --tag=passport-components
被發佈的元件將會被放到resources/js/components
目錄下。當元件被發布後,你應該在你的resources/js/app.js
檔案中註冊它們:
Vue.component( 'passport-clients', require('./components/passport/Clients.vue').default); Vue.component( 'passport-authorized-clients', require('./components/passport/AuthorizedClients.vue').default ); Vue.component( 'passport-personal-access-tokens', require('./components/passport/PersonalAccessTokens.vue').default );
{note} 在Laravel v5.7.19 之前,在註冊組件時新增“.default” 會導致控制台錯誤。有關此變更的解釋,請參閱Laravel Mix v4.0.0 發布說明.
在註冊了元件後,請確保執行npm run dev
來重新編譯你的資源。當你重編譯你的資源後,你可以將元件放到你應用的模板中以開始建立客戶端和個人存取權杖:
<passport-clients></passport-clients> <passport-authorized-clients></passport-authorized-clients>< passport-personal-access-tokens></passport-personal-access-tokens>
部署Passport
第一次在你的生產環境部署Passport 時,你大概需要執行passport:keys
指令。這個指令產生 Passport 產生存取權杖所需的金鑰。產生的金鑰一般情況下不應放在版本控制中:
php artisan passport:keys
可以使用Passport::loadKeysFrom
方法來自訂Passport 金鑰的載入路徑:
/** * 注册认证 / 授权服务 * * @return void */ public function boot(){ $this->registerPolicies(); Passport::routes(); Passport::loadKeysFrom('/secret-keys/oauth'); }
配置
令牌的有效期限
預設情況下,Passport 發放的存取權杖是有一年有效期限的。但是如果你想自訂存取權杖的有效期,可以使用 tokensExpireIn
和 refreshTokensExpireIn
方法。上述兩個方法同樣需要在AuthServiceProvider
的boot
方法中呼叫:
/** * 注册认证 / 授权服务 * * @return void */ public function boot(){ $this->registerPolicies(); Passport::routes(); Passport::tokensExpireIn(now()->addDays(15)); Passport::refreshTokensExpireIn(now()->addDays(30)); }# #覆寫預設模型可以自由擴充Passport 使用的模型,透過
Passport 類別自訂模型覆寫預設模型:
use App\Models\Passport\Client; use App\Models\Passport\AuthCode; use App\Models\Passport\TokenModel; use App\Models\Passport\PersonalAccessClient; /** * 注册认证 / 授权服务 * * @return void */ public function boot(){ $this->registerPolicies(); Passport::routes(); Passport::useClientModel(Client::class); Passport::useTokenModel(TokenModel::class); Passport::useAuthCodeModel(AuthCode::class); Passport::usePersonalAccessClientModel(PersonalAccessClient::class); }
發放存取權令牌
熟悉 OAuth2 的開發者一定知道, OAuth2 中不可或缺的部分就是授權碼。當使用授權碼時,客戶端應用程式會將使用者重新導向到你的伺服器,他們將批准或拒絕向客戶端發出存取權杖的請求。
管理客戶端
#首先,建立需要與應用程式API 互動的應用程序,開發人員將需要透過建立一個「客戶端」來註冊自己的應用程式。一般來說,這包括在使用者批准其授權請求後,提供其應用程式的名稱和應用程式可以重定向到的 URL。
The passport:client
指令
#建立客戶端最簡單的方式是使用Artisan 指令passport:client
,你可以使用此命令建立自己的客戶端,用於測試你的OAuth2 的功能。當你執行client
指令時,Passport 會提示你輸入有關客戶端的信息,最終會給你提供客戶端的ID 和金鑰:
php artisan passport:client
Redirect URLs
當有多個重定向URL 白名單時,可以在passport:client
指令提示輸入URL 時,使用逗號分隔來指定:
http://example.com/callback,http://examplefoo.com/callback
# {note} 任何包含逗號的URL 都必須進行編碼。
JSON API
考慮到你的使用者無法使用 client 指令,Passport 為此提供了可用於建立「客戶端」的 JSON API。這樣你就不用再花時間寫控制器來建立、更新和刪除客戶端。
然而,你仍舊需要基於 Passport 的 JSON API 開發一套前端介面,為你的使用者提供管理客戶端的面板。下面我們會列出所有用於管理客戶端的 API,為了方便起見,我們使用 Axios 來示範對連接埠發出 HTTP 請求。
這個 JSON API 由 web
和 auth
兩個中間件保護,所以只能從應用程式中調用,不能從外部調用。
{tip} 如果你不想自己實現整個客戶端管理的前端介面,可以使用 前端快速上手 在幾分鐘內組成一套功能齊全的前端介面。
GET /oauth/clients
此路由會傳回認證使用者的所有用戶端。主要用途是列出所有使用者的客戶端,以便他們可以編輯或刪除它們:
axios.get('/oauth/clients') .then(response => { console.log(response.data); });#
POST /oauth/clients
此路由用於建立新客戶端。它需要兩個參數:客戶端的名稱 name
和授權後回呼的 URL redirect
。在批准或拒絕授權請求後,使用者會被重定向到 redirect
參數提供的連結。
當客戶端建立後,會傳回客戶端的 ID 和金鑰。客戶端可以使用這兩個值從你的授權服務請求存取權杖 (Access token) 。此路由會傳回新的客戶端實例:
const data = { name: 'Client Name', redirect: 'http://example.com/callback'}; axios.post('/oauth/clients', data) .then(response => { console.log(response.data); }) .catch (response => { // 在response里列出错误详情... });
PUT /oauth/clients/{client-id}
此路由用於更新客戶端資訊。它需要兩個參數:客戶端的名稱 name
和授權後回呼的 URL redirect
。在批准或拒絕授權請求後,使用者會被重定向 redirect
到這個連結。此路由會傳回更新後的客戶端實例:
const data = { name: 'New Client Name', redirect: 'http://example.com/callback'}; axios.put('/oauth/clients/' + clientId, data) .then(response => { console.log(response.data); }) .catch (response => { // 在response里列出错误详情... });
DELETE /oauth/clients/{client-id}
##此路由用於刪除客戶端(client):axios.delete('/oauth/clients/' + clientId) .then(response => { // });要求令牌
客戶端建立之後,開發者會使用此客戶端的ID 和金鑰來請求授權程式碼,並從應用程式存取權杖。首先,存取應用程式的使用者向你應用程式的
/oauth/authorize 路由發出重定向請求,範例如下:Route::get('/redirect', function () {
$query = http_build_query([
'client_id' => 'client-id',
'redirect_uri' => 'http://example.com/callback',
'response_type' => 'code',
'scope' => '',
]);
return redirect('http://your-app.com/oauth/authorize?'.$query);
});
/oauth/authorize已經在
Passport::routes
方法中定義。你不需要手動定義此路由。
接收到授權請求時,Passport 會自動向使用者顯示一個模版頁面,允許使用者批准或拒絕授權請求。如果使用者批准請求,他們會被重定向回接入的應用程式指定的
redirect_uri。 redirect_uri
必須和客戶端建立時指定的 redirect
連結完全一致。 如果你想自訂授權確認頁面,可以使用 Artisan 指令
發佈 Passport 的檢視。發佈後的檢視檔案存放在 resources/views/vendor/passport
:php artisan vendor:publish --tag=passport-views
將授權碼轉換為存取權杖
使用者核准授權請求後,會被重新導向回接取的應用程式。然後接取應用程式應該將透過 POST
請求向你的應用程式申請存取權杖。請求應該包括當使用者批准授權請求時由應用程式發出的授權碼。在下面的範例中,我們使用Guzzle HTTP 函式庫來實作這次POST
要求:
Route::get('/callback', function (Request $request) { $http = new GuzzleHttp\Client; $response = $http->post('http://your-app.com/oauth/token', [ 'form_params' => [ 'grant_type' => 'authorization_code', 'client_id' => 'client-id', 'client_secret' => 'client-secret', 'redirect_uri' => 'http://example.com/callback', 'code' => $request->code, ], ]); return json_decode((string) $response->getBody(), true); });
路由/oauth/token
傳回的JSON 回應中會包含access_token
、refresh_token
和expires_in
屬性。 expires_in
屬性包含存取令牌的有效期限(單位:秒)。
{tip} 像
/oauth/authorize
路由一樣,/oauth/token
路由在Passport::routes
方法中定義了,你沒必要手動去定義它。預設情況下,此路由使用 “ThrottleRequests” 中間件的設定進行限流。
刷新令牌
如果你的應用程式發放了短期的存取令牌,用戶將需要透過在發出存取權杖時提供給他們的刷新令牌來刷新其存取權杖。在下面的範例中,我們使用Guzzle HTTP 函式庫來刷新令牌:
$http = new GuzzleHttp\Client; $response = $http->post('http://your-app.com/oauth/token', [ 'form_params' => [ 'grant_type' => 'refresh_token', 'refresh_token' => 'the-refresh-token', 'client_id' => 'client-id', 'client_secret' => 'client-secret', 'scope' => '', ],]); return json_decode((string) $response->getBody(), true);
路由/oauth/token
會傳回一個JSON 回應,其中包含access_token
、 refresh_token
和expires_in
屬性。 expires_in
屬性包含存取令牌的有效時間(單位:秒)。
已密碼授權令牌
OAuth2 密碼授權機制可以讓你自己的客戶端(如行動應用程式)使用郵箱地址或使用者名稱和密碼取得存取令牌。如此一來你就可以安全地向自己的客戶端發出存取令牌,而不需要遍歷整個OAuth2 授權程式碼重定向流程
##建立密碼授權客戶端在應用程式透過密碼授權機制來發布令牌之前,在passport:client 指令後面加上
--password參數來建立密碼授權的客戶端。如果你已經執行了
passport:install 指令,則不需要再執行此指令:
php artisan passport:client --password
請求令牌
建立密碼授權的用戶端後,就可以使用使用者的電子郵件地址和密碼向/oauth/token
路由發出POST
請求來獲取存取令牌。而該路由已經由 Passport::routes
方法註冊,因此不需要手動定義它。如果請求成功,會在服務端傳回的JSON 回應中收到一個access_token
和refresh_token
:
$http = new GuzzleHttp\Client; $response = $http->post('http://your-app.com/oauth/token', [ 'form_params' => [ 'grant_type' => 'password', 'client_id' => 'client-id', 'client_secret' => 'client-secret', 'username' => 'taylor@laravel.com', 'password' => 'my-password', 'scope' => '', ],]); return json_decode((string) $response->getBody(), true);
{tip} 預設情況下,訪問令牌是長期有效的。你可以根據需要 配置存取權杖的有效時間 。
請求所有作用域
使用密碼授權機制時,可以透過請求scope 參數*
來授權應用程式支援的所有範圍的令牌。如果你的請求中包含 scope 為 *
的參數,令牌實例上的 can
方法會始終傳回 true
。這種作用域的授權只能指派給使用password
授權時發出的令牌:
$response = $http->post('http://your-app.com/oauth/token', [ 'form_params' => [ 'grant_type' => 'password', 'client_id' => 'client-id', 'client_secret' => 'client-secret', 'username' => 'taylor@laravel.com', 'password' => 'my-password', 'scope' => '*', ], ]);##自訂使用者名字段當使用密碼授權時,Passport 預設使用
email 作為「使用者名稱」。但是,你可以透過在模型上定義一個
findForPassport 方法來自訂使用者名字段:
<?php namespace App; use Laravel\Passport\HasApiTokens; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable{ use HasApiTokens, Notifiable; /** * 通过用户名找到对应的用户信息 * * @param string $username * @return \App\User */ public function findForPassport($username) { return $this->where('username', $username)->first(); } }。式授權令牌
隱含授權類似於授權碼授權,但是它只將令牌傳回給客戶端而不交換授權碼。這種授權最常用於無法安全儲存客戶端憑證的 JavaScript 或行動應用程式。透過呼叫
AuthServiceProvider 中的
enableImplicitGrant
/** * 注册认证 / 授权服务 * * @return void */ public function boot(){ $this->registerPolicies(); Passport::routes(); Passport::enableImplicitGrant(); }
呼叫上面方法開啟授權後,開發者可以使用他們的客戶端ID 從應用程式請求存取令牌。存取的應用程式應該向你的應用程式的
/oauth/authorize 路由發出重定向請求,如下所示:####Route::get('/redirect', function () { $query = http_build_query([ 'client_id' => 'client-id', 'redirect_uri' => 'http://example.com/callback', 'response_type' => 'token', 'scope' => '', ]); return redirect('http://your-app.com/oauth/authorize?'.$query); });方法中定義好,所以無需再次手動定義此路由。
{tip} 注意,
/oauth/authorize路由已經在
Passport::routes
客戶端憑證授權令牌
客戶端憑證授權適用於機器到機器的認證。例如,你可以在透過 API 執行維護任務中使用此授權。
在客戶端憑證授權之前,需要先建立一個客戶端憑證授權的客戶端,你可以使用passport:client
指令的--client
參數來建立:
php artisan passport:client --client
接下來,要使用這個授權,你首先需要在app/Http/Kernel.php
的$routeMiddleware
變數中新增新的中間件:
use Laravel\Passport\Http\Middleware\CheckClientCredentials; protected $routeMiddleware = [ 'client' => CheckClientCredentials::class, ];
然後,在路由上追加這個中間件:
Route::get('/orders', function (Request $request) { ... })->middleware('client');
若要將對路由的存取限制在某個作用域內,可在將client
中間件附加到路由時提供以逗號分隔的所需作用域清單:
Route::get('/orders', function (Request $request) { ... })->middleware('client:check-status,your-scope');
#取得令牌
透過向oauth/token
介面發出請求來取得令牌:
$guzzle = new GuzzleHttp\Client; $response = $guzzle->post('http://your-app.com/oauth/token', [ 'form_params' => [ 'grant_type' => 'client_credentials', 'client_id' => 'client-id', 'client_secret' => 'client-secret', 'scope' => 'your-scope', ],]); return json_decode((string) $response->getBody(), true)['access_token'];
#個人存取權令牌
有時候,使用者要在不經過傳統的授權碼重定向流程的情況下向自己發出存取權杖。允許使用者透過應用程式使用者介面對自己發出令牌,有助於使用者體驗你的 API,或者也可以將其作為一種更簡單的發布存取令牌的方式。
{note} 個人存取權杖是永久有效的,就算使用了
tokensExpireIn
和refreshTokensExpireIn
方法也不會修改它的生命週期。
建立個人存取用戶端
在你的應用程式發布個人存取權杖之前,你需要在passport:client
指令後面帶上--personal
參數來建立對應的客戶端。如果你已經執行了passport:install
命令,則無需再執行此命令:
php artisan passport:client --personal
如果你已經建立了個人存取用戶端,你可以透過呼叫AuthServiceProvider
中的personalAccessClientId
方法來啟用:
/** * 注册认证 / 授权服务 * * @return void */ public function boot(){ $this->registerPolicies(); Passport::routes(); Passport::personalAccessClientId('client-id'); }
管理個人存取權杖
#建立個人存取客戶端後,你可以使用User
模型實例上的createToken
方法來為給定使用者發布令牌。 createToken
方法接受令牌的名稱作為其第一個參數和可選的 作用域 陣列作為其第二個參數:
$user = App\User::find(1); // 创建没有作用域的访问令牌... $token = $user->createToken('Token Name')->accessToken; // 创建有作用域的访问令牌... $token = $user->createToken('My Token', ['place-orders'])->accessToken;
JSON API
Passport 中也有用來管理個人存取權杖的 JSON API,你可以將其與自己的前端配對,為使用者提供管理個人存取權杖的儀表板。下面我們將介紹用於管理個人存取權杖的所有 API 介面。方便起見,我們使用 Axios 來示範對 API 的介面發出 HTTP 請求。
JSON API 由 web
和 auth
中間件保護;因此,只能從您自己的應用程式中呼叫它。無法從外部來源呼叫它。
{tip} 如果你不想實現自己的個人存取權杖管理的前端介面,可以根據 前端快速上手 在幾分鐘內組成功能齊全的前端介面。
GET /oauth/scopes
#此路由會傳回應用程式中定義的所有作用域 。你可以使用此路由列出使用者可能指派給個人存取權杖的範圍:
axios.get('/oauth/scopes') .then(response => { console.log(response.data); });
#GET /oauth/personal-access-tokens
##此路由傳回認證使用者建立的所有個人存取權令牌。這主要用於列出所有使用者的令牌,以便他們可以編輯或刪除它們:
axios.get('/oauth/personal-access-tokens') .then(response => { console.log(response.data); });
#POST /oauth/personal-access-tokens
#此路由用於建立新的個人存取令牌。它需要兩個資料:令牌的name
和scpoe
:
const data = { name: 'Token Name', scopes: []}; axios.post('/oauth/personal-access-tokens', data) .then(response => { console.log(response.data.accessToken); }) .catch (response => { // 列出响应中错误... });
DELETE /oauth/personal-access-tokens /{token-id}
此路由可用來刪除個人存取權杖:
axios.delete('/oauth/personal-access-tokens/' + tokenId);##路由保護透過中間件Passport 包含一個驗證保護機制可以驗證請求中傳入的存取令牌。配置
api 的看守器使用
passport 驅動程式後,只需要在需要有效存取權杖的任何路由上指定
auth:api 中間件:
Route::get('/user', function () { // })->middleware('auth:api');傳遞存取權杖當呼叫Passport 保護下的路由時,存取的API 應用程式需要將存取令牌作為
Bearer 令牌放在請求頭
Authorization 中。例如,使用 Guzzle HTTP 函式庫時:
$response = $client->request('GET', '/api/user', [ 'headers' => [ 'Accept' => 'application/json', 'Authorization' => 'Bearer '.$accessToken, ], ]);
令牌作用域
作用域可以讓 API 用戶端在請求帳戶授權時請求特定的權限。例如,如果你正在建立電子商務應用程序,並不是所有接入的 API 應用都需要下訂單的功能。你可以讓接入的 API 應用程式只被允許授權存取訂單出貨狀態。換句話說,作用域允許應用程式的使用者限制第三方應用程式執行的操作。
定義作用域
你可以在AuthServiceProvider
的boot
方法中使用Passport::tokensCan
方法來定義API 的作用域。 tokensCan
方法接受一個包含作用域名稱和描述的陣列作為參數。作用域描述將會在授權確認頁中直接顯示給用戶,你可以將其定義為任何你需要的內容:
use Laravel\Passport\Passport; Passport::tokensCan([ 'place-orders' => 'Place orders', 'check-status' => 'Check order status', ]);
預設作用域
如果客戶端沒有要求任何特定的範圍,你可以在AuthServiceProvider
的boot
方法中使用Passport::setDefaultScope
方法來定義預設的作用域。
use Laravel\Passport\Passport;Passport::setDefaultScope([ 'check-status', 'place-orders', ]);
給代幣分配作用域
請求授權碼
使用授權碼請求存取權杖時,存取的應用程式需為scope
參數指定所需作用域。 scope
參數包含多個作用域時,名稱之間使用空格分割:
Route::get('/redirect', function () { $query = http_build_query([ 'client_id' => 'client-id', 'redirect_uri' => 'http://example.com/callback', 'response_type' => 'code', 'scope' => 'place-orders check-status', ]); return redirect('http://your-app.com/oauth/authorize?'.$query);});
分發個人存取權杖
##使用 User 模型的
createToken 方法發放個人存取權杖時,可以將所需作用域的陣列作為第二個參數傳遞給此方法:
$token = $user->createToken('My Token', ['place-orders'])->accessToken;#檢查作用域Passport 包含兩個中介軟體,可用來驗證傳入的請求是否包含存取指定作用域的令牌。使用前,需要將下面的中間件加入
app/Http/Kernel.php 檔案的
$routeMiddleware 屬性:
'scopes' => \Laravel\Passport\Http\Middleware\CheckScopes::class, 'scope' => \Laravel\Passport\Http\Middleware\CheckForAnyScope::class,#檢查所有作用域路由可以使用
scopes 中間件來檢查目前請求是否擁有指定的
所有 作用域:
Route::get('/orders', function () { // Access token has both "check-status" and "place-orders" scopes... })->middleware('scopes:check-status,place-orders');#檢查任意作用域路由可以使用
scope 中間件來檢查目前請求是否擁有指定的
任意 作用域:
Route::get('/orders', function () { // 访问令牌具有 "check-status" 或 "place-orders" 作用域... })->middleware('scope:check-status,place-orders');
檢查令牌實例上的作用域
就算含有存取權杖驗證的請求已經通過應用程式的驗證,你仍然可以使用目前授權User
實例上的tokenCan
方法來驗證令牌是否擁有指定的作用域:
use Illuminate\Http\Request; Route::get('/orders', function (Request $request) { if ($request->user()->tokenCan('place-orders')) { // } });
#附加作用域方法
##scopeIds 方法將傳回所有已定義ID / 名稱的陣列:
Laravel\Passport\Passport::scopeIds();
scopes 方法將傳回一個包含所有已定義作用域陣列的
Laravel\Passport\Scope# 實例:
Laravel\Passport\Passport::scopes();
scopesFor 方法將傳回與給定ID / 名稱相符的
Laravel\Passport\Scope 實例陣列:
Laravel\Passport\Passport::scopesFor(['place-orders', 'check-status']);你可以使用
hasScope 方法決定是否已定義給定作用域:
Laravel\Passport\Passport::hasScope('place-orders');使用JavaScript 存取API
中間件加入到CreateFreshApiToken
在建構API 時, 如果能透過JavaScript 應用程式連接自己的API 將會為開發過程帶來極大的便利。這種 API 開發方法允許你使用自己的應用程式的 API 和別人共享的 API 。你的 Web 應用程式、行動應用程式、第三方應用程式以及可能在各種軟體包管理器上發布的任何 SDK 都可能會使用相同的 API 。
通常,如果要在 JavaScript 應用程式中使用 API ,需要手動向應用程式發送存取令牌,並將其傳遞給應用程式。但是, Passport 有一個可以處理這個問題的中間件。將
app/Http/Kernel.php 檔案中的
web
'web' => [ // 其他中间件... \Laravel\Passport\Http\Middleware\CreateFreshApiToken::class, ],
{note} 你應該確保在您的中間件堆疊中
CreateFreshApiToken 中間件之前列出了EncryptCookies
中間件。 這個 Passport 中間件將會在你所有的對外請求中加入一個
laravel_token cookie 。該 cookie 將包含一個加密後的 JWT , Passport 將用來驗證來自 JavaScript 應用程式的 API 請求。至此,你可以在不明確傳遞存取權杖的情況下向應用程式的API 發出請求:
axios.get('/api/user') .then(response => { console.log(response.data); });自訂Cookie 名稱如果需要,你可以在
AuthServiceProvider 的
boot 方法中使用
Passport::cookie
laravel_token cookie 的名稱。
/** * 注册认证 / 授权服务 * * @return void */ public function boot(){ $this->registerPolicies(); Passport::routes(); Passport::cookie('custom_name'); }CSRF 保護######當使用這種授權方法時,預設的Laravel JavaScript 鷹架會讓Axios 發送###X-CSRF-TOKEN### 和###X-Requested-With### 請求頭。另外,你必須確保 HTML meta 標籤 標籤 中包含了 CSRF 令牌:###
// In your application layout... <meta name="csrf-token" content="{{ csrf_token() }}"> // Laravel's JavaScript scaffolding... window.axios.defaults.headers.common = { 'X-Requested-With': 'XMLHttpRequest', };##################
事件
Passport 在發出存取權杖和刷新令牌時觸發事件。你可以在應用程式的EventServiceProvider
中為這些事件追加監聽器,並在監聽器中撤銷或修改其他令牌:
/** * 应用程序事件监听映射 * * @var array */ protected $listen = [ 'Laravel\Passport\Events\AccessTokenCreated' => [ 'App\Listeners\RevokeOldTokens', ], 'Laravel\Passport\Events\RefreshTokenCreated' => [ 'App\Listeners\PruneOldTokens', ], ];
測試
Passport 的actingAs
方法可以指定目前已認證使用者及其作用域。 actingAs
方法的第一個參數是使用者實例,第二個參數是使用者令牌作用域數組:
use App\User; use Laravel\Passport\Passport; public function testServerCreation(){ Passport::actingAs( factory(User::class)->create(), ['create-servers'] ); $response = $this->post('/api/create-server'); $response->assertStatus(201); }