簡介 (Introduction)
除了提供內建的 認證 服務外,Laravel 還提供了一種簡單的方式來授權使用者對給定資源的動作。例如,即使使用者已經認證,他們可能沒有被授權更新或刪除由您的應用程式管理的某些 Eloquent models 或資料庫記錄。Laravel 的授權功能提供了一種簡單、有組織的方式來管理這些類型的授權檢查。
Laravel 提供兩種主要的授權動作方式:gates 和 policies。可以把 gates 和 policies 想像成路由和 controllers。Gates 提供一種簡單的、基於閉包的授權方法,而 policies,像 controllers 一樣,圍繞特定的 model 或資源組織邏輯。在本文件中,我們將首先探索 gates,然後檢視 policies。
在建立應用程式時,您不需要在專門使用 gates 或專門使用 policies 之間做選擇。大多數應用程式很可能會包含 gates 和 policies 的某種混合,這完全沒問題!Gates 最適用於與任何 model 或資源無關的動作,例如檢視管理員儀表板。相反,當您希望授權對特定 model 或資源的動作時,應該使用 policies。
Gates
撰寫 Gates (Writing Gates)
[!WARNING] Gates 是學習 Laravel 授權功能基礎的好方法;但是,在建立強大的 Laravel 應用程式時,您應該考慮使用 policies 來組織您的授權規則。
Gates 只是確定使用者是否被授權執行給定動作的閉包。通常,gates 在 App\Providers\AppServiceProvider 類別的 boot 方法中使用 Gate facade 定義。Gates 始終接收使用者實例作為其第一個引數,並可選擇性地接收額外的引數,例如相關的 Eloquent model。
在這個範例中,我們將定義一個 gate 來確定使用者是否可以更新給定的 App\Models\Post model。該 gate 將透過比較使用者的 id 與建立文章的使用者的 user_id 來完成此操作:
use App\Models\Post;
use App\Models\User;
use Illuminate\Support\Facades\Gate;
/**
* 啟動任何應用程式服務。
*/
public function boot(): void
{
Gate::define('update-post', function (User $user, Post $post) {
return $user->id === $post->user_id;
});
}
像 controllers 一樣,gates 也可以使用類別回呼陣列定義:
use App\Policies\PostPolicy;
use Illuminate\Support\Facades\Gate;
/**
* 啟動任何應用程式服務。
*/
public function boot(): void
{
Gate::define('update-post', [PostPolicy::class, 'update']);
}
授權動作 (Authorizing Actions)
若要使用 gates 授權動作,您應該使用 Gate facade 提供的 allows 或 denies 方法。請注意,您不需要將目前已認證的使用者傳遞給這些方法。Laravel 會自動負責將使用者傳遞到 gate 閉包中。通常在執行需要授權的動作之前,在應用程式的 controllers 中呼叫 gate 授權方法:
<?php
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
class PostController extends Controller
{
/**
* 更新給定的文章。
*/
public function update(Request $request, Post $post): RedirectResponse
{
if (! Gate::allows('update-post', $post)) {
abort(403);
}
// 更新文章...
return redirect('/posts');
}
}
如果您想確定目前已認證使用者以外的使用者是否被授權執行動作,您可以使用 Gate facade 上的 forUser 方法:
if (Gate::forUser($user)->allows('update-post', $post)) {
// 使用者可以更新文章...
}
if (Gate::forUser($user)->denies('update-post', $post)) {
// 使用者無法更新文章...
}
您可以使用 any 或 none 方法一次授權多個動作:
if (Gate::any(['update-post', 'delete-post'], $post)) {
// 使用者可以更新或刪除文章...
}
if (Gate::none(['update-post', 'delete-post'], $post)) {
// 使用者無法更新或刪除文章...
}
授權或拋出例外 (Authorizing Or Throwing Exceptions)
如果您想嘗試授權動作並在使用者不被允許執行給定動作時自動拋出 Illuminate\Auth\Access\AuthorizationException,您可以使用 Gate facade 的 authorize 方法。AuthorizationException 的實例會由 Laravel 自動轉換為 403 HTTP 回應:
Gate::authorize('update-post', $post);
// 該動作已授權...
提供額外的上下文 (Gates Supplying Additional Context)
用於授權能力的 gate 方法(allows、denies、check、any、none、authorize、can、cannot)和授權 Blade 指令(@can、@cannot、@canany)可以接收陣列作為其第二個引數。這些陣列元素作為參數傳遞給 gate 閉包,並可用於在做出授權決定時提供額外的上下文:
use App\Models\Category;
use App\Models\User;
use Illuminate\Support\Facades\Gate;
Gate::define('create-post', function (User $user, Category $category, bool $pinned) {
if (! $user->canPublishToGroup($category->group)) {
return false;
} elseif ($pinned && ! $user->canPinPosts()) {
return false;
}
return true;
});
if (Gate::check('create-post', [$category, $pinned])) {
// 使用者可以建立文章...
}
Gate 回應 (Gate Responses)
到目前為止,我們只檢視了回傳簡單布林值的 gates。但是,有時您可能希望回傳更詳細的回應,包括錯誤訊息。若要這樣做,您可以從 gate 回傳 Illuminate\Auth\Access\Response:
use App\Models\User;
use Illuminate\Auth\Access\Response;
use Illuminate\Support\Facades\Gate;
Gate::define('edit-settings', function (User $user) {
return $user->isAdmin
? Response::allow()
: Response::deny('您必須是管理員。');
});
即使從 gate 回傳授權回應,Gate::allows 方法仍將回傳簡單的布林值;但是,您可以使用 Gate::inspect 方法來取得 gate 回傳的完整授權回應:
$response = Gate::inspect('edit-settings');
if ($response->allowed()) {
// 該動作已授權...
} else {
echo $response->message();
}
當使用 Gate::authorize 方法時,如果動作未被授權會拋出 AuthorizationException,授權回應提供的錯誤訊息將被傳播到 HTTP 回應:
Gate::authorize('edit-settings');
// 該動作已授權...
自訂 HTTP 回應狀態 (Customizing Gate Response Status)
當動作透過 Gate 被拒絕時,會回傳 403 HTTP 回應;但是,有時回傳替代的 HTTP 狀態碼可能很有用。您可以使用 Illuminate\Auth\Access\Response 類別上的 denyWithStatus 靜態建構函式來自訂失敗授權檢查回傳的 HTTP 狀態碼:
use App\Models\User;
use Illuminate\Auth\Access\Response;
use Illuminate\Support\Facades\Gate;
Gate::define('edit-settings', function (User $user) {
return $user->isAdmin
? Response::allow()
: Response::denyWithStatus(404);
});
因為透過 404 回應隱藏資源是 Web 應用程式的常見模式,所以為了方便起見提供了 denyAsNotFound 方法:
use App\Models\User;
use Illuminate\Auth\Access\Response;
use Illuminate\Support\Facades\Gate;
Gate::define('edit-settings', function (User $user) {
return $user->isAdmin
? Response::allow()
: Response::denyAsNotFound();
});
攔截 Gate 檢查 (Intercepting Gate Checks)
有時,您可能希望授予特定使用者所有能力。您可以使用 before 方法定義一個在所有其他授權檢查之前執行的閉包:
use App\Models\User;
use Illuminate\Support\Facades\Gate;
Gate::before(function (User $user, string $ability) {
if ($user->isAdministrator()) {
return true;
}
});
如果 before 閉包回傳非 null 結果,該結果將被視為授權檢查的結果。
您可以使用 after 方法定義在所有其他授權檢查之後執行的閉包:
use App\Models\User;
Gate::after(function (User $user, string $ability, bool|null $result, mixed $arguments) {
if ($user->isAdministrator()) {
return true;
}
});
after 閉包回傳的值不會覆蓋授權檢查的結果,除非 gate 或 policy 回傳 null。
內聯授權 (Inline Authorization)
有時,您可能希望確定目前已認證的使用者是否被授權執行給定動作,而無需撰寫對應於該動作的專用 gate。Laravel 允許您透過 Gate::allowIf 和 Gate::denyIf 方法執行這些類型的「內聯」授權檢查。內聯授權不會執行任何定義的 「before」或「after」授權鉤子:
use App\Models\User;
use Illuminate\Support\Facades\Gate;
Gate::allowIf(fn (User $user) => $user->isAdministrator());
Gate::denyIf(fn (User $user) => $user->banned());
如果動作未被授權或目前沒有使用者已認證,Laravel 將自動拋出 Illuminate\Auth\Access\AuthorizationException 例外。AuthorizationException 的實例會由 Laravel 的例外處理程序自動轉換為 403 HTTP 回應。
建立 Policies (Creating Policies)
產生 Policies (Generating Policies)
Policies 是圍繞特定 model 或資源組織授權邏輯的類別。例如,如果您的應用程式是一個部落格,您可能有一個 App\Models\Post model 和對應的 App\Policies\PostPolicy 來授權使用者動作,例如建立或更新文章。
您可以使用 make:policy Artisan 命令產生 policy。產生的 policy 將放置在 app/Policies 目錄中。如果此目錄不存在於您的應用程式中,Laravel 將為您建立它:
php artisan make:policy PostPolicy
make:policy 命令將產生一個空的 policy 類別。如果您想產生一個包含與檢視、建立、更新和刪除資源相關的範例 policy 方法的類別,您可以在執行命令時提供 --model 選項:
php artisan make:policy PostPolicy --model=Post
註冊 Policies (Registering Policies)
Policy 發現 (Policy Discovery)
預設情況下,只要 model 和 policy 遵循標準的 Laravel 命名慣例,Laravel 就會自動發現 policies。具體來說,policies 必須位於包含您的 models 的目錄或其上層的 Policies 目錄中。因此,例如,models 可能放置在 app/Models 目錄中,而 policies 可能放置在 app/Policies 目錄中。在這種情況下,Laravel 將先在 app/Models/Policies 中檢查 policies,然後在 app/Policies 中檢查。此外,policy 名稱必須與 model 名稱相符並具有 Policy 後綴。因此,User model 將對應於 UserPolicy policy 類別。
如果您想定義自己的 policy 發現邏輯,您可以使用 Gate::guessPolicyNamesUsing 方法註冊自訂的 policy 發現回呼。通常,此方法應該從應用程式的 AppServiceProvider 的 boot 方法中呼叫:
use Illuminate\Support\Facades\Gate;
Gate::guessPolicyNamesUsing(function (string $modelClass) {
// 回傳給定 model 的 policy 類別名稱...
});
手動註冊 Policies (Manually Registering Policies)
使用 Gate facade,您可以在應用程式的 AppServiceProvider 的 boot 方法中手動註冊 policies 及其對應的 models:
use App\Models\Order;
use App\Policies\OrderPolicy;
use Illuminate\Support\Facades\Gate;
/**
* 啟動任何應用程式服務。
*/
public function boot(): void
{
Gate::policy(Order::class, OrderPolicy::class);
}
或者,您可以在 model 類別上放置 UsePolicy 屬性來通知 Laravel 該 model 對應的 policy:
<?php
namespace App\Models;
use App\Policies\OrderPolicy;
use Illuminate\Database\Eloquent\Attributes\UsePolicy;
use Illuminate\Database\Eloquent\Model;
#[UsePolicy(OrderPolicy::class)]
class Order extends Model
{
//
}
撰寫 Policies (Writing Policies)
Policy 方法 (Policy Methods)
一旦 policy 類別已註冊,您可以為它授權的每個動作新增方法。例如,讓我們在 PostPolicy 上定義一個 update 方法,用於確定給定的 App\Models\User 是否可以更新給定的 App\Models\Post 實例。
update 方法將接收 User 和 Post 實例作為其引數,並應回傳 true 或 false 以指示使用者是否被授權更新給定的 Post。因此,在此範例中,我們將驗證使用者的 id 是否與文章上的 user_id 相符:
<?php
namespace App\Policies;
use App\Models\Post;
use App\Models\User;
class PostPolicy
{
/**
* 確定使用者是否可以更新給定的文章。
*/
public function update(User $user, Post $post): bool
{
return $user->id === $post->user_id;
}
}
您可以繼續在 policy 上根據它授權的各種動作的需要定義額外的方法。例如,您可能定義 view 或 delete 方法來授權各種與 Post 相關的動作,但請記住您可以自由地為 policy 方法取任何您喜歡的名稱。
如果您在透過 Artisan 控制台產生 policy 時使用了 --model 選項,它將已經包含 viewAny、view、create、update、delete、restore 和 forceDelete 動作的方法。
[!NOTE] 所有 policies 都透過 Laravel service container 解析,允許您在 policy 的建構函式中型別提示任何需要的依賴項以自動注入它們。
Policy 回應 (Policy Responses)
到目前為止,我們只檢視了回傳簡單布林值的 policy 方法。但是,有時您可能希望回傳更詳細的回應,包括錯誤訊息。若要這樣做,您可以從 policy 方法回傳 Illuminate\Auth\Access\Response 實例:
use App\Models\Post;
use App\Models\User;
use Illuminate\Auth\Access\Response;
/**
* 確定使用者是否可以更新給定的文章。
*/
public function update(User $user, Post $post): Response
{
return $user->id === $post->user_id
? Response::allow()
: Response::deny('您不擁有此文章。');
}
當從 policy 回傳授權回應時,Gate::allows 方法仍將回傳簡單的布林值;但是,您可以使用 Gate::inspect 方法來取得 gate 回傳的完整授權回應:
use Illuminate\Support\Facades\Gate;
$response = Gate::inspect('update', $post);
if ($response->allowed()) {
// 該動作已授權...
} else {
echo $response->message();
}
當使用 Gate::authorize 方法時,如果動作未被授權會拋出 AuthorizationException,授權回應提供的錯誤訊息將被傳播到 HTTP 回應:
Gate::authorize('update', $post);
// 該動作已授權...
自訂 HTTP 回應狀態 (Customizing Policy Response Status)
當動作透過 policy 方法被拒絕時,會回傳 403 HTTP 回應;但是,有時回傳替代的 HTTP 狀態碼可能很有用。您可以使用 Illuminate\Auth\Access\Response 類別上的 denyWithStatus 靜態建構函式來自訂失敗授權檢查回傳的 HTTP 狀態碼:
use App\Models\Post;
use App\Models\User;
use Illuminate\Auth\Access\Response;
/**
* 確定使用者是否可以更新給定的文章。
*/
public function update(User $user, Post $post): Response
{
return $user->id === $post->user_id
? Response::allow()
: Response::denyWithStatus(404);
}
因為透過 404 回應隱藏資源是 Web 應用程式的常見模式,所以為了方便起見提供了 denyAsNotFound 方法:
use App\Models\Post;
use App\Models\User;
use Illuminate\Auth\Access\Response;
/**
* 確定使用者是否可以更新給定的文章。
*/
public function update(User $user, Post $post): Response
{
return $user->id === $post->user_id
? Response::allow()
: Response::denyAsNotFound();
}
不需要 Models 的方法 (Methods Without Models)
某些 policy 方法只接收目前已認證使用者的實例。這種情況在授權 create 動作時最為常見。例如,如果您正在建立一個部落格,您可能希望確定使用者是否被授權建立任何文章。在這些情況下,您的 policy 方法應該只期望接收使用者實例:
/**
* 確定給定的使用者是否可以建立文章。
*/
public function create(User $user): bool
{
return $user->role == 'writer';
}
訪客使用者 (Guest Users)
預設情況下,如果傳入的 HTTP 請求不是由已認證的使用者發起的,所有 gates 和 policies 都會自動回傳 false。但是,您可以透過宣告「可選的」型別提示或為使用者引數定義提供 null 預設值,允許這些授權檢查傳遞到您的 gates 和 policies:
<?php
namespace App\Policies;
use App\Models\Post;
use App\Models\User;
class PostPolicy
{
/**
* 確定使用者是否可以更新給定的文章。
*/
public function update(?User $user, Post $post): bool
{
return $user?->id === $post->user_id;
}
}
Policy 過濾器 (Policy Filters)
對於某些使用者,您可能希望授權給定 policy 中的所有動作。若要完成此操作,請在 policy 上定義 before 方法。before 方法將在 policy 上的任何其他方法之前執行,讓您有機會在實際呼叫預期的 policy 方法之前授權動作。此功能最常用於授權應用程式管理員執行任何動作:
use App\Models\User;
/**
* 執行預先授權檢查。
*/
public function before(User $user, string $ability): bool|null
{
if ($user->isAdministrator()) {
return true;
}
return null;
}
如果您想拒絕特定類型使用者的所有授權檢查,您可以從 before 方法回傳 false。如果回傳 null,授權檢查將落入 policy 方法。
[!WARNING] 如果 policy 類別不包含與正在檢查的能力名稱相符的方法,則不會呼叫該類別的
before方法。
使用 Policies 授權動作 (Authorizing Actions Using Policies)
透過 User Model (Via the User Model)
Laravel 應用程式中包含的 App\Models\User model 包含兩個用於授權動作的有用方法:can 和 cannot。can 和 cannot 方法接收您希望授權的動作名稱和相關的 model。例如,讓我們確定使用者是否被授權更新給定的 App\Models\Post model。通常,這將在 controller 方法中完成:
<?php
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
class PostController extends Controller
{
/**
* 更新給定的文章。
*/
public function update(Request $request, Post $post): RedirectResponse
{
if ($request->user()->cannot('update', $post)) {
abort(403);
}
// 更新文章...
return redirect('/posts');
}
}
如果給定 model 已 註冊 policy,can 方法將自動呼叫適當的 policy 並回傳布林結果。如果沒有為該 model 註冊 policy,can 方法將嘗試呼叫與給定動作名稱相符的基於閉包的 Gate。
不需要 Models 的動作 (User Model Actions That Dont Require Models)
請記住,某些動作可能對應於像 create 這樣不需要 model 實例的 policy 方法。在這些情況下,您可以將類別名稱傳遞給 can 方法。類別名稱將用於確定在授權動作時使用哪個 policy:
<?php
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
class PostController extends Controller
{
/**
* 建立文章。
*/
public function store(Request $request): RedirectResponse
{
if ($request->user()->cannot('create', Post::class)) {
abort(403);
}
// 建立文章...
return redirect('/posts');
}
}
透過 Gate Facade (Via the Gate Facade)
除了 App\Models\User model 提供的有用方法外,您始終可以透過 Gate facade 的 authorize 方法授權動作。
像 can 方法一樣,此方法接受您希望授權的動作名稱和相關的 model。如果動作未被授權,authorize 方法將拋出 Illuminate\Auth\Access\AuthorizationException 例外,Laravel 例外處理程序將自動將其轉換為具有 403 狀態碼的 HTTP 回應:
<?php
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
class PostController extends Controller
{
/**
* 更新給定的部落格文章。
*
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function update(Request $request, Post $post): RedirectResponse
{
Gate::authorize('update', $post);
// 目前使用者可以更新部落格文章...
return redirect('/posts');
}
}
不需要 Models 的動作 (Controller Actions That Dont Require Models)
如前所述,某些 policy 方法(如 create)不需要 model 實例。在這些情況下,您應該將類別名稱傳遞給 authorize 方法。類別名稱將用於確定在授權動作時使用哪個 policy:
use App\Models\Post;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
/**
* 建立新的部落格文章。
*
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function create(Request $request): RedirectResponse
{
Gate::authorize('create', Post::class);
// 目前使用者可以建立部落格文章...
return redirect('/posts');
}
透過 Middleware (Via Middleware)
Laravel 包含一個 middleware,可以在傳入請求到達您的路由或 controllers 之前授權動作。預設情況下,Illuminate\Auth\Middleware\Authorize middleware 可以使用 can middleware 別名 附加到路由,該別名由 Laravel 自動註冊。讓我們探索一個使用 can middleware 授權使用者可以更新文章的範例:
use App\Models\Post;
Route::put('/post/{'{post}'}', function (Post $post) {
// 目前使用者可以更新文章...
})->middleware('can:update,post');
在此範例中,我們傳遞給 can middleware 兩個引數。第一個是我們希望授權的動作名稱,第二個是我們希望傳遞給 policy 方法的路由參數。在這種情況下,由於我們使用 隱式 model 綁定,App\Models\Post model 將被傳遞給 policy 方法。如果使用者未被授權執行給定動作,middleware 將回傳具有 403 狀態碼的 HTTP 回應。
為方便起見,您也可以使用 can 方法將 can middleware 附加到您的路由:
use App\Models\Post;
Route::put('/post/{'{post}'}', function (Post $post) {
// 目前使用者可以更新文章...
})->can('update', 'post');
不需要 Models 的動作 (Middleware Actions That Dont Require Models)
同樣,某些 policy 方法(如 create)不需要 model 實例。在這些情況下,您可以將類別名稱傳遞給 middleware。類別名稱將用於確定在授權動作時使用哪個 policy:
Route::post('/post', function () {
// 目前使用者可以建立文章...
})->middleware('can:create,App\Models\Post');
在字串 middleware 定義中指定整個類別名稱可能會變得繁瑣。因此,您可以選擇使用 can 方法將 can middleware 附加到您的路由:
use App\Models\Post;
Route::post('/post', function () {
// 目前使用者可以建立文章...
})->can('create', Post::class);
透過 Blade Templates (Via Blade Templates)
撰寫 Blade templates 時,您可能希望僅在使用者被授權執行給定動作時顯示頁面的一部分。例如,您可能希望僅在使用者實際可以更新文章時顯示部落格文章的更新表單。在這種情況下,您可以使用 @can 和 @cannot 指令:
@can('update', $post)
<!-- 目前使用者可以更新文章... -->
@elsecan('create', App\Models\Post::class)
<!-- 目前使用者可以建立新文章... -->
@else
<!-- ... -->
@endcan
@cannot('update', $post)
<!-- 目前使用者無法更新文章... -->
@elsecannot('create', App\Models\Post::class)
<!-- 目前使用者無法建立新文章... -->
@endcannot
這些指令是撰寫 @if 和 @unless 陳述式的便捷快捷方式。上面的 @can 和 @cannot 陳述式等同於以下陳述式:
@if (Auth::user()->can('update', $post))
<!-- 目前使用者可以更新文章... -->
@endif
@unless (Auth::user()->can('update', $post))
<!-- 目前使用者無法更新文章... -->
@endunless
您也可以確定使用者是否被授權執行給定動作陣列中的任何動作。若要完成此操作,請使用 @canany 指令:
@canany(['update', 'view', 'delete'], $post)
<!-- 目前使用者可以更新、檢視或刪除文章... -->
@elsecanany(['create'], \App\Models\Post::class)
<!-- 目前使用者可以建立文章... -->
@endcanany
不需要 Models 的動作 (Blade Actions That Dont Require Models)
像大多數其他授權方法一樣,如果動作不需要 model 實例,您可以將類別名稱傳遞給 @can 和 @cannot 指令:
@can('create', App\Models\Post::class)
<!-- 目前使用者可以建立文章... -->
@endcan
@cannot('create', App\Models\Post::class)
<!-- 目前使用者無法建立文章... -->
@endcannot
提供額外的上下文 (Supplying Additional Context)
當使用 policies 授權動作時,您可以將陣列作為第二個引數傳遞給各種授權函數和輔助工具。陣列中的第一個元素將用於確定應調用哪個 policy,而其餘的陣列元素將作為參數傳遞給 policy 方法,並可用於在做出授權決定時提供額外的上下文。例如,考慮以下包含額外 $category 參數的 PostPolicy 方法定義:
/**
* 確定使用者是否可以更新給定的文章。
*/
public function update(User $user, Post $post, int $category): bool
{
return $user->id === $post->user_id &&
$user->canUpdateCategory($category);
}
當嘗試確定已認證使用者是否可以更新給定文章時,我們可以像這樣調用此 policy 方法:
/**
* 更新給定的部落格文章。
*
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function update(Request $request, Post $post): RedirectResponse
{
Gate::authorize('update', [$post, $request->category]);
// 目前使用者可以更新部落格文章...
return redirect('/posts');
}
授權與 Inertia (Authorization & Inertia)
雖然授權必須始終在伺服器上處理,但為您的前端應用程式提供授權資料以正確呈現應用程式的 UI 通常很方便。Laravel 沒有定義將授權資訊公開給 Inertia 驅動的前端的必需慣例。
但是,如果您使用的是 Laravel 基於 Inertia 的 starter kits,您的應用程式已經包含一個 HandleInertiaRequests middleware。在此 middleware 的 share 方法中,您可以回傳將提供給應用程式中所有 Inertia 頁面的共享資料。此共享資料可以作為為使用者定義授權資訊的便利位置:
<?php
namespace App\Http\Middleware;
use App\Models\Post;
use Illuminate\Http\Request;
use Inertia\Middleware;
class HandleInertiaRequests extends Middleware
{
// ...
/**
* 定義預設共享的 props。
*
* @return array<string, mixed>
*/
public function share(Request $request)
{
return [
...parent::share($request),
'auth' => [
'user' => $request->user(),
'permissions' => [
'post' => [
'create' => $request->user()->can('create', Post::class),
],
],
],
];
}
}