# Laravel 的 API 認證系統 Passport
- [介紹](#introduction)
- [安裝](#installation)
- [前端快速上手](#frontend-quickstart)
- [部署 Passport](#deploying-passport)
- [配置](#configuration)
- [令牌的使用期限](#token-lifetimes)
- [發放訪問令牌](#issuing-access-tokens)
- [管理客戶端](#managing-clients)
- [請求令牌](#requesting-tokens)
- [刷新令牌](#refreshing-tokens)
- [密碼授權令牌](#password-grant-tokens)
- [創建密碼授權客戶端](#creating-a-password-grant-client)
- [請求密碼授權令牌](#requesting-password-grant-tokens)
- [請求所有作用域](#requesting-all-scopes)
- [簡化授權令牌](#implicit-grant-tokens)
- [客戶端授權令牌](#client-credentials-grant-tokens)
- [私人訪問令牌](#personal-access-tokens)
- [創建私人訪問令牌的客戶端](#creating-a-personal-access-client)
- [管理私人訪問令牌](#managing-personal-access-tokens)
- [路由保護](#protecting-routes)
- [通過中間件](#via-middleware)
- [傳遞訪問令牌](#passing-the-access-token)
- [令牌作用域](#token-scopes)
- [定義作用域](#defining-scopes)
- [給令牌分派作用域](#assigning-scopes-to-tokens)
- [檢查作用域](#checking-scopes)
- [使用 JavaScript 接入 API](#consuming-your-api-with-javascript)
- [事件](#events)
- [測試](#testing)
<a name="introduction"></a>
## 介紹
在 Laravel 中,實現基于傳統表單的登陸和授權已經非常簡單,但是如何滿足 API 場景下的授權需求呢?在 API 場景里通常通過令牌來實現用戶授權,而非維護請求之間的 Session 狀態。現在 Laravel 項目中可以使用 Passport 輕而易舉地實現 API 授權過程,通過 Passport 可以在幾分鐘之內為你的應用程序添加完整的 OAuth2 服務端實現。 Passport 基于 [League OAuth2 server](https://github.com/thephpleague/oauth2-server) 該項目的維護人是 [Alex Bilbie](https://github.com/alexbilbie)。
> {note} 本文檔假定你已熟悉 OAuth2 。如果你并不了解 OAuth2 ,閱讀之前請先熟悉下 OAuth2 的常用術語和基本特征。
<a name="installation"></a>
## 安裝
使用 Composer 依賴包管理器安裝 Passport :
composer require laravel/passport
接下來,將 Passport 的服務提供者注冊到配置文件 `config/app.php` 的 `providers` 數組中:
Laravel\Passport\PassportServiceProvider::class,
Passport 使用服務提供者注冊內部的數據庫遷移腳本目錄,所以上一步完成后,你需要更新你的數據庫結構。Passport 的遷移腳本會自動創建應用程序需要的客戶端數據表和令牌數據表:
php artisan migrate
> {note} 如果你不打算使用 Passport 的默認遷移,你應該在 `AppServiceProvider` 的 `register` 方法中調用 `Passport :: ignoreMigrations` 方法。 你可以導出這個默認遷移用 `php artisan vendor:publish --tag=passport-migrations` 命令。
接下來,你需要運行 `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
{
/**
* The policy mappings for the application.
*
* @var array
*/
protected $policies = [
'App\Model' => 'App\Policies\ModelPolicy',
];
/**
* Register any authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
Passport::routes();
}
}
最后,需要將配置文件 `config/auth.php` 中 `api` 部分的授權保護項( `driver` )改為 `passport` 。此調整會讓你的應用程序在接收到 API 的授權請求時使用 Passport 的 `TokenGuard` 來處理:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
<a name="frontend-quickstart"></a>
### 前端快速上手
> {note} 如果想要使用 Passport 的 Vue 組件,那么你必須使用 [Vue](https://vuejs.org) Javascript 框架,另外這些組件還用到了 Bootstrap CSS 框架。當然你也可以不使用上面的任何工具,但在實現你自己的前端部分時,Passport 的 Vue 組件仍舊有很高的參考價值。
Passport 配備了一些可以讓你的用戶自行創建客戶端和私人訪問令牌的 JSON API。所以,你可以自己花時間來編寫一些前端代碼來使用這些 API。當然在 Passport 中也已經預制了一些 [Vue](https://vuejs.org) 組件,你可以直接使用這些示例代碼,也可以基于這些代碼實現自己的前端部分。
使用 Artisan 命令 `vendor:publish` 來發布 Passport 的 Vue 組件:
php artisan vendor:publish --tag=passport-components
已發布的組件將被放置在 `resources/assets/js/components` 目錄中,可以在 `resources/assets/js/app.js` 文件中注冊這些已發布的組件:
Vue.component(
'passport-clients',
require('./components/passport/Clients.vue')
);
Vue.component(
'passport-authorized-clients',
require('./components/passport/AuthorizedClients.vue')
);
Vue.component(
'passport-personal-access-tokens',
require('./components/passport/PersonalAccessTokens.vue')
);
這些組件注冊后,請保證運行 `npm run dev` 命令重新編譯你的代碼。一旦你重新編譯了代碼,你可以直接將這些組件直接放入應用程序的模板中,用于創建客戶端和私人訪問令牌:
<passport-clients></passport-clients>
<passport-authorized-clients></passport-authorized-clients>
<passport-personal-access-tokens></passport-personal-access-tokens>
<a name="deploying-passport"></a>
### 部署 Passport
第一次部署 Passport 到生產服務器時,可能會需要運行 `passport:keys` 命令。該命令生成 Passport 所需要的加密密鑰,來產生訪問令牌。這些生成的密鑰往往不保存在源碼控制中:
php artisan passport:keys
<a name="configuration"></a>
## 配置
<a name="token-lifetimes"></a>
### 令牌的有效期
默認情況下,Passport 發放的訪問令牌是永久有效的,不需要刷新。但是如果你想給訪問令牌配置一個短一些的有效期,那你就需要用到 `tokensExpireIn` 和 `refreshTokensExpireIn` 方法了,上述兩個方法同樣需要在 `AuthServiceProvider` 的 `boot` 方法中調用:
use Carbon\Carbon;
/**
* Register any authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
Passport::routes();
Passport::tokensExpireIn(Carbon::now()->addDays(15));
Passport::refreshTokensExpireIn(Carbon::now()->addDays(30));
}
<a name="issuing-access-tokens"></a>
## 發放訪問令牌
熟悉 OAuth2 的開發者一定知道, OAuth2 中必不可少的部分就是授權碼。在獲取授權碼時,接入應用會重定向一個用戶到你的服務端,用戶可以選擇允許或拒絕向這個客戶端發放訪問令牌。
<a name="managing-clients"></a>
### 管理客戶端
首先,接入應用如果想要與你應用的 API 進行交互,必須先在你的應用程序中注冊一個「客戶端」。一般來說,這個注冊過程需要開發者提供兩部分信息:接入應用名稱和用戶授權后的跳轉鏈接。
#### 命令 `passport:client`
創建客戶端最簡單的方式是使用 Artisan 命令 `passport:client` ,你可以使用此命令創建自己的客戶端,用于測試 OAuth2 的功能。在你執行 `client` 命令時,Passport 會提示輸入更多關于你的客戶端的信息,最終會提供給你生成的客戶端的 ID 和 密鑰:
php artisan passport:client
#### JSON API
考慮到你的用戶們并沒有辦法使用 `client` 命令,Passport 同時提供了用戶創建客戶端的 JSON API 。這樣你就不用再花時間編碼來實現客戶端創建、更新和刪除的相關控制器邏輯了。
然而,你仍舊需要基于 Passport 的 JSON API 開發一套前端界面,方便你的用戶管理他們授權的客戶端。下面我們會列出所有用于管理客戶端的 API,方便起見,我們使用 [Axios](https://github.com/mzabriskie/axios) 展示對 API 的 HTTP 請求。
> {tip} 如果你不想自己重寫整個客戶端管理的前端界面,可以根據 [前端快速上手](#frontend-quickstart) 在幾分鐘內組建一套功能完備的前端界面。
#### `GET /oauth/clients`
此接口會返回當前認證用戶的所有客戶端。主要用途是列出當前用戶所有客戶端,方便用戶修改或刪除:
axios.get('/oauth/clients')
.then(response => {
console.log(response.data);
});
#### `POST /oauth/clients`
此接口用于用戶創建新的客戶端。它需要兩部分數據:客戶端的名稱、客戶端的 `redirect` 鏈接。當用戶允許或拒絕授權請求后,用戶都會被重定向到這個 `redirect` 鏈接。
當客戶端創建完成后,會生成此客戶端的 ID 和密鑰,客戶端可以使用這兩個值從你的應用程序請求訪問令牌。此接口會返回新建客戶端實例的信息:
const data = {
name: 'Client Name',
redirect: 'http://example.com/callback'
};
axios.post('/oauth/clients', data)
.then(response => {
console.log(response.data);
})
.catch (response => {
// List errors on response...
});
#### `PUT /oauth/clients/{client-id}`
此接口用于更新客戶端信息。它需要兩部分數據:客戶端的 `name` 和 `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 => {
// List errors on response...
});
#### `DELETE /oauth/clients/{client-id}`
此接口用于刪除客戶端:
axios.delete('/oauth/clients/' + clientId)
.then(response => {
//
});
<a name="requesting-tokens"></a>
### 請求令牌
#### 授權時的重定向
客戶端創建之后,開發者會使用此客戶端的 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);
});
> {tip} 注意,路由 `/oauth/authorize` 已經在 `Passport::routes` 方法中定
#### 確認授權請求
接收到授權請求時,Passport 會顯示默認的授權確認頁面,用戶可以允許或拒絕本次授權請求。用戶確認后會被重定向回接入應用程序請求中指定的 `redirect_uri` 鏈接。`redirect_uri` 必須和客戶端創建時提供的 `redirect` 完全一致。
如果你想自定義授權確認頁面,可以使用 Artisan 命令 `vendor:publish` 發布 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` 方法中定義,所以無需再次定義。
<a name="refreshing-tokens"></a>
### 刷新令牌
如果你的應用程序發放了短期訪問令牌,用戶需要刷新訪問令牌時,需要提供與訪問令牌同時發放的刷新令牌。在下面的例子中,我們使用 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` 屬性值即當前訪問令牌的有效時間(單位:秒)。
<a name="password-grant-tokens"></a>
## 密碼授權令牌
OAuth2 密碼授權機制可以讓自有應用基于郵箱地址(用戶名)和密碼獲取訪問令牌,自有應用比如你的手機客戶端。這樣就允許自由應用無需跳轉步驟即可通過整個 OAuth2 的授權過程。
<a name="creating-a-password-grant-client"></a>
### 創建密碼授權客戶端
如果想要通過密碼授權機制來發布令牌,首先你需要創建一個密碼授權客戶端。你可以使用帶有 `--password` 參數的 `passport:client` 命令。如果你已經運行了 `passport:install` 命令,那無需再單獨運行此命令:
php artisan passport:client --password
<a name="requesting-password-grant-tokens"></a>
### 請求密碼授權令牌
當你創建密碼授權客戶端后,你可以向 `/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} 注意:訪問令牌默認是永久有效的。但是如果需要你可以 [配置你應用程序的訪問令牌有效時間](#configuration)。
<a name="requesting-all-scopes"></a>
### 請求所有作用域
使用密碼授權機制時,你可以通過請求作用域 `*` 讓你的令牌獲取應用程序中定義的所有作用域。在處理使用此令牌發起的請求時,`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' => '*',
],
]);
<a name="implicit-grant-tokens"></a>
## 簡化授權令牌
簡化授權和通過授權碼授權相似; 區別是, 不需要通過授權碼去獲取令牌而是把令牌直接返回客戶端. 主要用在無法安全存儲證書場景中,這種授權在 JavaScript 和 移動應用 是最常用的. 開啟授權, 在 `AuthServiceProvider` 中調用 `enableImplicitGrant` 方法:
/**
* Register any authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
Passport::routes();
Passport::enableImplicitGrant();
}
調用上面方法開啟授權后, 開發者可以通過自己的應用把 client 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` 中,所以無需再次手動定義。
<a name="client-credentials-grant-tokens"></a>
## 客戶端證書授權令牌
客戶端證書授權適用于機器對機器認證,例如,你可以在通過API執行腳本任務中使用此授權。要使用這種授權,你首先需要在 `app/Http/Kernel.php` 的 `$routeMiddleware` 變量中添加新的中間件:
use Laravel\Passport\Http\Middleware\CheckClientCredentials::class;
protected $routeMiddleware = [
'client' => CheckClientCredentials::class,
];
然后將這個中間件附加到路由中:
Route::get('/user', function(Request $request) {
...
})->middleware('client');
要獲取令牌,向 `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',
],
]);
echo json_decode((string) $response->getBody(), true);
<a name="personal-access-tokens"></a>
## 私人訪問令牌
有些時候你的用戶可能想發布一個訪問令牌自己使用,又不想經歷通常的授權跳轉流程,這時候如果能讓用戶在你的應用程序中自行發放訪問令牌,在試驗 API 接口或者在簡單的授權演示中,是一個不錯的解決方案。
> {note} 私人訪問令牌總是永久有效的,`tokensExpireIn` 和 `refreshTokensExpireIn` 方法不會影響它的有效期。
<a name="creating-a-personal-access-client"></a>
### 創建私人訪問客戶端
發布私人訪問令牌之前,你需要先創建對應的客戶端。你可以使用帶 `--personal` 參數的 `passport:client` 命令來創建,如果你已經運行了 `passport:install` 命令,那無需再運行此命令:
php artisan passport:client --personal
<a name="managing-personal-access-tokens"></a>
### 管理私人訪問令牌
創建私人訪問客戶端后,你可以使用 `User` 模型實例上的 `createToken` 方法來為給定用戶發布令牌, `createToken` 方法的第一個參數為令牌名稱,第二個參數(可選)是 [作用域](#token-scopes) 列表:
$user = App\User::find(1);
// Creating a token without scopes...
$token = $user->createToken('Token Name')->accessToken;
// Creating a token with scopes...
$token = $user->createToken('My Token', ['place-orders'])->accessToken;
#### JSON API
Passport 中也有用來管理私人訪問令牌的 JSON API,你可以基于這些 API 開發一套前端操作界面供給用戶管理自己的私人訪問令牌。下面我們會列出所有管理私人訪問令牌的 API。方便起見,我們使用 [Axios](https://github.com/mzabriskie/axios) 展示對 API 的 HTTP 請求。
> {tip} 如果你不想自己重寫整個私人訪問令牌管理的前端界面,可以根據 [前端快速上手](#frontend-quickstart) 在幾分鐘內組建一套功能完備的前端界面。
#### `GET /oauth/scopes`
此接口會返回應用程序中定義的所有 [作用域](#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` ) 作用域 ( `scopes` ):
const data = {
name: 'Token Name',
scopes: []
};
axios.post('/oauth/personal-access-tokens', data)
.then(response => {
console.log(response.data.accessToken);
})
.catch (response => {
// List errors on response...
});
#### `DELETE /oauth/personal-access-tokens/{token-id}`
此接口用于刪除私人訪問令牌:
axios.delete('/oauth/personal-access-tokens/' + tokenId);
<a name="protecting-routes"></a>
## 路由保護
<a name="via-middleware"></a>
### 通過中間件
Passport 包含一個 [驗證保護機制](/docs/{{version}}/authentication#adding-custom-guards) 可以驗證請求中的的訪問令牌。 前面i將 `api` 中的保護機制改為為 `passport` 后,你只要給需要驗證訪問令牌的路由添加 `auth:api` 中間件,該機制將發揮作用:
Route::get('/user', function () {
//
})->middleware('auth:api');
<a name="passing-the-access-token"></a>
### 傳遞訪問令牌
接入應用在調用 Passport 保護下的路由時,需要將訪問令牌作為 `Bearer` 令牌放在請求頭 `Authorization` 中。在下面的例子中,我們使用 Guzzle HTTP 庫來實現這次 `POST` 請求:
$response = $client->request('GET', '/api/user', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer '.$accessToken,
],
]);
<a name="token-scopes"></a>
## 令牌作用域
<a name="defining-scopes"></a>
### 定義作用域
當 API 客戶端接入特定用戶時,可以通過作用域來限定其訪問權限。例如在你編寫的電子商務應用中,一些接入應用可以獲取訂單的發貨狀態而不能創建訂單。換言之,作用域能夠讓你的用戶限制第三方應用的行為,從而保障自身的利益。
你可以使用 `Passport::tokensCan` 方法來定義 API 的作用域,定義代碼需要放置在 `AuthServiceProvider` 的 `boot` 方法中。`tokensCan` 方法接受一個包含作用域名稱、描述的數組作為參數。作用域描述將會在授權確認頁中直接展示給用戶,你可以將其定義為任何你需要的內容:
use Laravel\Passport\Passport;
Passport::tokensCan([
'place-orders' => 'Place orders',
'check-status' => 'Check order status',
]);
<a name="assigning-scopes-to-tokens"></a>
### 給令牌分派作用域
#### 授權碼機制
使用授權碼機制申請訪問令牌時,接入應用可以通過 `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;
<a name="checking-scopes"></a>
### 檢查作用域
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 () {
// Access token has either "check-status" or "place-orders" scope...
})->middleware('scope:check-status,place-orders');
#### 檢查特定令牌實例的作用域
接入應用使用訪問令牌通過你應用程序的驗證后,你仍然可以使用當前授權 `User` 實例上的 `tokenCan` 方法來驗證此令牌是否擁有指定的作用域:
use Illuminate\Http\Request;
Route::get('/orders', function (Request $request) {
if ($request->user()->tokenCan('place-orders')) {
//
}
});
<a name="consuming-your-api-with-javascript"></a>
## 使用 JavaScript 接入 API
在構建 API 時,如果能通過 JavaScript 應用接入自己的 API 將會給開發過程帶來極大的便利。這樣你可以與所用人一樣使用你自己的應用程序的 API,同樣的 API 可以被你自己的 web 應用、移動應用、第三方應用以及你發布到各個包管理平臺的 SDK 共同使用。
通常,在你通過 JavaScript 接入你的 API 時,每次請求你的應用程序時都需要手動傳遞訪問令牌,然而,Passport 其中一個中間件可以幫你做這件事,你需要做的僅僅是將 `CreateFreshApiToken` 中間件添加到你的 `web` 中間件組中:
'web' => [
// Other middleware...
\Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,
],
Passport 的這個中間件將會在你所有的對外請求中添加一個 `laravel_token` cookie ,該 cookie 將包含一個加密后的 [JWT](https://jwt.io/) ,Passport 可以根據此數據判斷你 JavaScript 應用的授權狀態。至此,你可以無需傳遞訪問令牌直接請求應用程序的 API 了:
axios.get('/user')
.then(response => {
console.log(response.data);
});
當使用上面方法授權時,Axios 會自動帶上 `X-CSRF-TOKEN` 請求頭傳遞。另外,默認的 Laravel JavaScript 也會帶上 `X-Requested-With` 請求頭:
window.axios.defaults.headers.common = {
'X-Requested-With': 'XMLHttpRequest',
};
> {note} 如果你用了其他 JavaScript 框架,需要確保每次對外請求都會帶有 `X-CSRF-TOKEN` 和?`X-Requested-With` 請求頭。
<a name="events"></a>
## 事件
Passport 在訪問令牌和刷新令牌時觸發事件。 你可以通過觸發這些事件來修改或刪除數據庫中的其他訪問令牌。 你可以在應用程序的 `EventServiceProvider` 中為這些事件附加監聽器:
```php
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
'Laravel\Passport\Events\AccessTokenCreated' => [
'App\Listeners\RevokeOldTokens',
],
'Laravel\Passport\Events\RefreshTokenCreated' => [
'App\Listeners\PruneOldTokens',
],
];
```
<a name="testing"></a>
## 測試
Passport 的 `actingAs` 方法可以用于指定當前認證的用戶及其授權范圍。 `actingAs` 方法第一個參數是一個對象,第二個參數是數組表示申請的授權范圍:
public function testServerCreation()
{
Passport::actingAs(
factory(User::class)->create(),
['create-servers']
);
$response = $this->post('/api/create-server');
$response->assertStatus(200);
}
## 譯者署名
| 用戶名 | 頭像 | 職能 | 簽名 |
|---|---|---|---|
| [@Kirisky](https://github.com/kirisky) | <img class="avatar-66 rm-style" src="https://dn-phphub.qbox.me/uploads/avatars/18491_1503379318.jpeg?imageView2/1/w/100/h/100"> | 翻譯 | 部分關鍵字翻譯參考 [@KevinDiamen](https://github.com/KevinDiamen) |
| Cloes | <img class="avatar-66 rm-style" src="https://dn-phphub.qbox.me/uploads/avatars/6187_1477389867.jpg?imageView2/1/w/100/h/100"> | 翻譯 | 我的[github](https://github.com/cloes) |
---
> {note} 歡迎任何形式的轉載,但請務必注明出處,尊重他人勞動共創開源社區。
>
> 轉載請注明:本文檔由 Laravel China 社區 [laravel-china.org](https://laravel-china.org) 組織翻譯,詳見 [翻譯召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
>
> 文檔永久地址: https://d.laravel-china.org
- 說明
- 翻譯說明
- 發行說明
- 升級說明
- 貢獻導引
- 入門指南
- 安裝
- 配置信息
- 文件夾結構
- HomeStead
- Valet
- 核心架構
- 請求周期
- 服務容器
- 服務提供者
- 門面(Facades)
- Contracts
- 基礎功能
- 路由
- 中間件
- CSRF 保護
- 控制器
- 請求
- 響應
- 視圖
- 重定向
- Session
- 表單驗證
- 錯誤與日志
- 前端開發
- Blade 模板
- 本地化
- 前端指南
- 編輯資源 Mix
- 安全
- 用戶認證
- API認證
- 用戶授權
- 加密解密
- 哈希
- 重置密碼
- 綜合話題
- Artisan 命令行
- 廣播系統
- 緩存系統
- 集合
- 事件系統
- 文件存儲
- 輔助函數
- 郵件發送
- 消息通知
- 擴展包開發
- 隊列
- 任務調度
- 數據庫
- 快速入門
- 查詢構造器
- 分頁
- 數據庫遷移
- 數據填充
- Redis
- Eloquent ORM
- 快速入門
- 模型關聯
- Eloquent 集合
- 修改器
- API 資源
- 序列化
- 測試
- 快速入門
- HTTP 測試
- 瀏覽器測試 Dusk
- 數據庫測試
- 測試模擬器
- 官方擴展包
- Cashier 交易工具包
- Envoy 部署工具
- Horizon
- Passport OAuth 認證
- Scout 全文搜索
- Socialite 社交化登錄
- 交流說明