跳轉至內容

授權

簡介

除了提供內建的 身份驗證 服務外,Laravel 還提供了一種簡單的方法來針對給定資源授權使用者操作。例如,即使一個使用者已透過身份驗證,他們也可能無權更新或刪除由您的應用程式管理的某些 Eloquent 模型或資料庫記錄。Laravel 的授權功能提供了一種簡單、有組織的方式來管理這些型別的授權檢查。

Laravel 提供了兩種主要的授權動作方式:門面(Gates)策略(Policies)。可以將門面和策略想象成路由和控制器。門面提供了一種簡單的、基於閉包的授權方法,而策略則像控制器一樣,圍繞特定的模型或資源對邏輯進行分組。在本文件中,我們將先探索門面,然後再研究策略。

在構建應用程式時,您無需在僅使用門面或僅使用策略之間做出選擇。大多數應用程式很可能包含門面和策略的混合,這完全沒問題!門面最適用於與任何模型或資源無關的動作,例如檢視管理員儀表板。相比之下,當您希望授權特定模型或資源的動作時,應使用策略。

門面(Gates)

編寫門面

門面是學習 Laravel 授權功能基礎知識的好方法;但是,在構建健壯的 Laravel 應用程式時,您應該考慮使用 策略 來組織您的授權規則。

門面只是決定使用者是否有權執行給定動作的閉包。通常,門面是在 App\Providers\AppServiceProvider 類的 boot 方法中使用 Gate 門面定義的。門面總是接收一個使用者例項作為其第一個引數,並且可以選擇接收其他引數,例如相關的 Eloquent 模型。

在此示例中,我們將定義一個門面來確定使用者是否可以更新給定的 App\Models\Post 模型。門面將透過將使用者的 id 與建立該帖子的使用者的 user_id 進行比較來實現這一點

1use App\Models\Post;
2use App\Models\User;
3use Illuminate\Support\Facades\Gate;
4 
5/**
6 * Bootstrap any application services.
7 */
8public function boot(): void
9{
10 Gate::define('update-post', function (User $user, Post $post) {
11 return $user->id === $post->user_id;
12 });
13}

像控制器一樣,門面也可以使用類回撥陣列來定義

1use App\Policies\PostPolicy;
2use Illuminate\Support\Facades\Gate;
3 
4/**
5 * Bootstrap any application services.
6 */
7public function boot(): void
8{
9 Gate::define('update-post', [PostPolicy::class, 'update']);
10}

授權動作

要使用門面授權動作,您應該使用 Gate 門面提供的 allowsdenies 方法。請注意,您不需要將當前經過身份驗證的使用者傳遞給這些方法。Laravel 會自動處理將使用者傳遞到門面閉包中。通常在執行需要授權的動作之前,在應用程式的控制器中呼叫門面授權方法

1<?php
2 
3namespace App\Http\Controllers;
4 
5use App\Models\Post;
6use Illuminate\Http\RedirectResponse;
7use Illuminate\Http\Request;
8use Illuminate\Support\Facades\Gate;
9 
10class PostController extends Controller
11{
12 /**
13 * Update the given post.
14 */
15 public function update(Request $request, Post $post): RedirectResponse
16 {
17 if (! Gate::allows('update-post', $post)) {
18 abort(403);
19 }
20 
21 // Update the post...
22 
23 return redirect('/posts');
24 }
25}

如果您想確定除當前經過身份驗證的使用者之外的其他使用者是否有權執行動作,可以使用 Gate 門面上的 forUser 方法

1if (Gate::forUser($user)->allows('update-post', $post)) {
2 // The user can update the post...
3}
4 
5if (Gate::forUser($user)->denies('update-post', $post)) {
6 // The user can't update the post...
7}

您可以使用 anynone 方法一次授權多個動作

1if (Gate::any(['update-post', 'delete-post'], $post)) {
2 // The user can update or delete the post...
3}
4 
5if (Gate::none(['update-post', 'delete-post'], $post)) {
6 // The user can't update or delete the post...
7}

授權或丟擲異常

如果您想嘗試授權一個動作,並且在使用者不允許執行給定動作時自動丟擲 Illuminate\Auth\Access\AuthorizationException,可以使用 Gate 門面的 authorize 方法。Laravel 會自動將 AuthorizationException 例項轉換為 403 HTTP 響應

1Gate::authorize('update-post', $post);
2 
3// The action is authorized...

提供額外上下文

用於授權能力的門面方法(allowsdeniescheckanynoneauthorizecancannot)和授權 Blade 指令@can@cannot@canany)可以將陣列作為其第二個引數。這些陣列元素作為引數傳遞給門面閉包,並可在進行授權決策時用於提供額外的上下文

1use App\Models\Category;
2use App\Models\User;
3use Illuminate\Support\Facades\Gate;
4 
5Gate::define('create-post', function (User $user, Category $category, bool $pinned) {
6 if (! $user->canPublishToGroup($category->group)) {
7 return false;
8 } elseif ($pinned && ! $user->canPinPosts()) {
9 return false;
10 }
11 
12 return true;
13});
14 
15if (Gate::check('create-post', [$category, $pinned])) {
16 // The user can create the post...
17}

門面響應

到目前為止,我們只檢查了返回簡單布林值的門面。但是,有時您可能希望返回更詳細的響應,包括錯誤訊息。為此,您可以從門面返回一個 Illuminate\Auth\Access\Response

1use App\Models\User;
2use Illuminate\Auth\Access\Response;
3use Illuminate\Support\Facades\Gate;
4 
5Gate::define('edit-settings', function (User $user) {
6 return $user->isAdmin
7 ? Response::allow()
8 : Response::deny('You must be an administrator.');
9});

即使您從門面返回了授權響應,Gate::allows 方法仍然會返回一個簡單的布林值;但是,您可以使用 Gate::inspect 方法來獲取門面返回的完整授權響應

1$response = Gate::inspect('edit-settings');
2 
3if ($response->allowed()) {
4 // The action is authorized...
5} else {
6 echo $response->message();
7}

當使用 Gate::authorize 方法(如果動作未被授權則丟擲 AuthorizationException)時,授權響應提供的錯誤訊息將傳播到 HTTP 響應中

1Gate::authorize('edit-settings');
2 
3// The action is authorized...

自定義 HTTP 響應狀態

當透過門面拒絕動作時,會返回 403 HTTP 響應;然而,有時返回替代的 HTTP 狀態程式碼會很有用。您可以使用 Illuminate\Auth\Access\Response 類上的 denyWithStatus 靜態建構函式自定義授權檢查失敗時返回的 HTTP 狀態程式碼

1use App\Models\User;
2use Illuminate\Auth\Access\Response;
3use Illuminate\Support\Facades\Gate;
4 
5Gate::define('edit-settings', function (User $user) {
6 return $user->isAdmin
7 ? Response::allow()
8 : Response::denyWithStatus(404);
9});

因為透過 404 響應隱藏資源是 Web 應用程式的一種常見模式,所以為了方便起見,提供了 denyAsNotFound 方法

1use App\Models\User;
2use Illuminate\Auth\Access\Response;
3use Illuminate\Support\Facades\Gate;
4 
5Gate::define('edit-settings', function (User $user) {
6 return $user->isAdmin
7 ? Response::allow()
8 : Response::denyAsNotFound();
9});

攔截門面檢查

有時,您可能希望授予特定使用者所有能力。您可以使用 before 方法定義一個在所有其他授權檢查之前執行的閉包

1use App\Models\User;
2use Illuminate\Support\Facades\Gate;
3 
4Gate::before(function (User $user, string $ability) {
5 if ($user->isAdministrator()) {
6 return true;
7 }
8});

如果 before 閉包返回一個非 null 的結果,則該結果將被視為授權檢查的結果。

您可以使用 after 方法定義一個在所有其他授權檢查之後執行的閉包

1use App\Models\User;
2 
3Gate::after(function (User $user, string $ability, bool|null $result, mixed $arguments) {
4 if ($user->isAdministrator()) {
5 return true;
6 }
7});

除非門面或策略返回了 null,否則 after 閉包返回的值不會覆蓋授權檢查的結果。

內聯授權

有時,您可能希望在不編寫與動作對應的專用門面的情況下,確定當前經過身份驗證的使用者是否有權執行給定動作。Laravel 允許您透過 Gate::allowIfGate::denyIf 方法執行這些型別的“內聯”授權檢查。內聯授權不會執行任何已定義的 “之前”或“之後”授權鉤子

1use App\Models\User;
2use Illuminate\Support\Facades\Gate;
3 
4Gate::allowIf(fn (User $user) => $user->isAdministrator());
5 
6Gate::denyIf(fn (User $user) => $user->banned());

如果動作未被授權,或者當前沒有任何使用者經過身份驗證,Laravel 會自動丟擲 Illuminate\Auth\Access\AuthorizationException 異常。Laravel 的異常處理程式會自動將 AuthorizationException 例項轉換為 403 HTTP 響應。

建立策略(Policies)

生成策略

策略是圍繞特定模型或資源組織授權邏輯的類。例如,如果您的應用程式是一個部落格,您可能有一個 App\Models\Post 模型和一個對應的 App\Policies\PostPolicy,用於授權建立或更新帖子等使用者動作。

您可以使用 make:policy Artisan 命令生成策略。生成的策略將放置在 app/Policies 目錄中。如果您的應用程式中不存在此目錄,Laravel 將為您建立它

1php artisan make:policy PostPolicy

make:policy 命令將生成一個空的策略類。如果您想生成一個包含與檢視、建立、更新和刪除資源相關的示例策略方法的類,可以在執行命令時提供 --model 選項

1php artisan make:policy PostPolicy --model=Post

註冊策略

策略發現

預設情況下,只要模型和策略遵循標準的 Laravel 命名約定,Laravel 就會自動發現策略。具體來說,策略必須位於包含模型的目錄或其上方的 Policies 目錄中。例如,模型可以放在 app/Models 目錄中,而策略可以放在 app/Policies 目錄中。在這種情況下,Laravel 將檢查 app/Models/Policies,然後檢查 app/Policies。此外,策略名稱必須與模型名稱匹配並具有 Policy 字尾。因此,User 模型將對應於 UserPolicy 策略類。

如果您想定義自己的策略發現邏輯,可以使用 Gate::guessPolicyNamesUsing 方法註冊自定義策略發現回撥。通常,此方法應從應用程式的 AppServiceProviderboot 方法中呼叫

1use Illuminate\Support\Facades\Gate;
2 
3Gate::guessPolicyNamesUsing(function (string $modelClass) {
4 // Return the name of the policy class for the given model...
5});

手動註冊策略

使用 Gate 門面,您可以在應用程式的 AppServiceProviderboot 方法中手動註冊策略及其對應的模型

1use App\Models\Order;
2use App\Policies\OrderPolicy;
3use Illuminate\Support\Facades\Gate;
4 
5/**
6 * Bootstrap any application services.
7 */
8public function boot(): void
9{
10 Gate::policy(Order::class, OrderPolicy::class);
11}

或者,您可以在模型類上放置 UsePolicy 屬性,以通知 Laravel 該模型對應的策略

1<?php
2 
3namespace App\Models;
4 
5use App\Policies\OrderPolicy;
6use Illuminate\Database\Eloquent\Attributes\UsePolicy;
7use Illuminate\Database\Eloquent\Model;
8 
9#[UsePolicy(OrderPolicy::class)]
10class Order extends Model
11{
12 //
13}

編寫策略

策略方法

一旦註冊了策略類,您就可以為它授權的每個動作新增方法。例如,讓我們在 PostPolicy 上定義一個 update 方法,該方法確定給定的 App\Models\User 是否可以更新給定的 App\Models\Post 例項。

update 方法將接收一個 User 和一個 Post 例項作為其引數,並應返回 truefalse,指示使用者是否有權更新給定的 Post。因此,在此示例中,我們將驗證使用者的 id 是否與帖子上的 user_id 匹配

1<?php
2 
3namespace App\Policies;
4 
5use App\Models\Post;
6use App\Models\User;
7 
8class PostPolicy
9{
10 /**
11 * Determine if the given post can be updated by the user.
12 */
13 public function update(User $user, Post $post): bool
14 {
15 return $user->id === $post->user_id;
16 }
17}

您可以根據需要繼續在策略上定義其他方法,以用於它授權的各種動作。例如,您可以定義 viewdelete 方法來授權各種與 Post 相關的動作,但請記住,您可以隨意為策略方法命名。

如果您在透過 Artisan 控制檯生成策略時使用了 --model 選項,它將已經包含用於 viewAnyviewcreateupdatedeleterestoreforceDelete 動作的方法。

所有策略都透過 Laravel 服務容器 解析,允許您在策略的建構函式中對任何所需的依賴項進行型別提示,從而使它們被自動注入。

策略響應

到目前為止,我們只檢查了返回簡單布林值的策略方法。但是,有時您可能希望返回更詳細的響應,包括錯誤訊息。為此,您可以從策略方法返回一個 Illuminate\Auth\Access\Response 例項

1use App\Models\Post;
2use App\Models\User;
3use Illuminate\Auth\Access\Response;
4 
5/**
6 * Determine if the given post can be updated by the user.
7 */
8public function update(User $user, Post $post): Response
9{
10 return $user->id === $post->user_id
11 ? Response::allow()
12 : Response::deny('You do not own this post.');
13}

當從策略返回授權響應時,Gate::allows 方法仍然會返回一個簡單的布林值;但是,您可以使用 Gate::inspect 方法來獲取門面返回的完整授權響應

1use Illuminate\Support\Facades\Gate;
2 
3$response = Gate::inspect('update', $post);
4 
5if ($response->allowed()) {
6 // The action is authorized...
7} else {
8 echo $response->message();
9}

當使用 Gate::authorize 方法(如果動作未被授權則丟擲 AuthorizationException)時,授權響應提供的錯誤訊息將傳播到 HTTP 響應中

1Gate::authorize('update', $post);
2 
3// The action is authorized...

自定義 HTTP 響應狀態

當透過策略方法拒絕動作時,會返回 403 HTTP 響應;然而,有時返回替代的 HTTP 狀態程式碼會很有用。您可以使用 Illuminate\Auth\Access\Response 類上的 denyWithStatus 靜態建構函式自定義授權檢查失敗時返回的 HTTP 狀態程式碼

1use App\Models\Post;
2use App\Models\User;
3use Illuminate\Auth\Access\Response;
4 
5/**
6 * Determine if the given post can be updated by the user.
7 */
8public function update(User $user, Post $post): Response
9{
10 return $user->id === $post->user_id
11 ? Response::allow()
12 : Response::denyWithStatus(404);
13}

因為透過 404 響應隱藏資源是 Web 應用程式的一種常見模式,所以為了方便起見,提供了 denyAsNotFound 方法

1use App\Models\Post;
2use App\Models\User;
3use Illuminate\Auth\Access\Response;
4 
5/**
6 * Determine if the given post can be updated by the user.
7 */
8public function update(User $user, Post $post): Response
9{
10 return $user->id === $post->user_id
11 ? Response::allow()
12 : Response::denyAsNotFound();
13}

無需模型的方法

有些策略方法只接收當前經過身份驗證的使用者例項。這種情況在授權 create 動作時最常見。例如,如果您正在建立一個部落格,您可能希望確定使用者是否有權建立任何帖子。在這些情況下,您的策略方法應該只期望接收一個使用者例項

1/**
2 * Determine if the given user can create posts.
3 */
4public function create(User $user): bool
5{
6 return $user->role == 'writer';
7}

訪客使用者

預設情況下,如果傳入的 HTTP 請求不是由經過身份驗證的使用者發起的,所有門面和策略都會自動返回 false。但是,您可以透過宣告“可選”型別提示或為使用者引數定義提供 null 預設值,允許這些授權檢查傳遞到您的門面和策略中

1<?php
2 
3namespace App\Policies;
4 
5use App\Models\Post;
6use App\Models\User;
7 
8class PostPolicy
9{
10 /**
11 * Determine if the given post can be updated by the user.
12 */
13 public function update(?User $user, Post $post): bool
14 {
15 return $user?->id === $post->user_id;
16 }
17}

策略過濾器

對於某些使用者,您可能希望授權給定策略內的所有動作。要實現這一點,請在策略上定義一個 before 方法。before 方法將在策略上的任何其他方法之前執行,讓您有機會在實際呼叫預期的策略方法之前授權該動作。此功能最常用於授權應用程式管理員執行任何動作

1use App\Models\User;
2 
3/**
4 * Perform pre-authorization checks.
5 */
6public function before(User $user, string $ability): bool|null
7{
8 if ($user->isAdministrator()) {
9 return true;
10 }
11 
12 return null;
13}

如果您想拒絕特定型別使用者的所有授權檢查,那麼您可以從 before 方法返回 false。如果返回 null,則授權檢查將流向策略方法。

如果類不包含名稱與正在檢查的能力名稱相匹配的方法,則不會呼叫策略類的 before 方法。

使用策略授權動作

透過使用者模型

您的 Laravel 應用程式中包含的 App\Models\User 模型包含兩個用於授權動作的有益方法:cancannotcancannot 方法接收您想要授權的動作名稱和相關的模型。例如,讓我們確定使用者是否有權更新給定的 App\Models\Post 模型。通常,這將在控制器方法中完成

1<?php
2 
3namespace App\Http\Controllers;
4 
5use App\Models\Post;
6use Illuminate\Http\RedirectResponse;
7use Illuminate\Http\Request;
8 
9class PostController extends Controller
10{
11 /**
12 * Update the given post.
13 */
14 public function update(Request $request, Post $post): RedirectResponse
15 {
16 if ($request->user()->cannot('update', $post)) {
17 abort(403);
18 }
19 
20 // Update the post...
21 
22 return redirect('/posts');
23 }
24}

如果為給定的模型 註冊了策略,則 can 方法將自動呼叫適當的策略並返回布林結果。如果沒有為模型註冊策略,can 方法將嘗試呼叫與給定動作名稱匹配的基於閉包的門面。

不需要模型的方法

請記住,某些動作可能對應於不需要模型例項的 create 等策略方法。在這些情況下,您可以將類名傳遞給 can 方法。類名將用於確定在授權動作時使用哪個策略

1<?php
2 
3namespace App\Http\Controllers;
4 
5use App\Models\Post;
6use Illuminate\Http\RedirectResponse;
7use Illuminate\Http\Request;
8 
9class PostController extends Controller
10{
11 /**
12 * Create a post.
13 */
14 public function store(Request $request): RedirectResponse
15 {
16 if ($request->user()->cannot('create', Post::class)) {
17 abort(403);
18 }
19 
20 // Create the post...
21 
22 return redirect('/posts');
23 }
24}

透過 Gate 門面

除了 App\Models\User 模型提供的有用方法外,您還可以隨時透過 Gate 門面的 authorize 方法授權動作。

can 方法一樣,此方法接受您想要授權的動作名稱和相關的模型。如果動作未被授權,authorize 方法將丟擲 Illuminate\Auth\Access\AuthorizationException 異常,Laravel 異常處理程式將自動將其轉換為具有 403 狀態程式碼的 HTTP 響應

1<?php
2 
3namespace App\Http\Controllers;
4 
5use App\Models\Post;
6use Illuminate\Http\RedirectResponse;
7use Illuminate\Http\Request;
8use Illuminate\Support\Facades\Gate;
9 
10class PostController extends Controller
11{
12 /**
13 * Update the given blog post.
14 *
15 * @throws \Illuminate\Auth\Access\AuthorizationException
16 */
17 public function update(Request $request, Post $post): RedirectResponse
18 {
19 Gate::authorize('update', $post);
20 
21 // The current user can update the blog post...
22 
23 return redirect('/posts');
24 }
25}

不需要模型的方法

如前所述,某些像 create 這樣的策略方法不需要模型例項。在這些情況下,您應該將類名傳遞給 authorize 方法。類名將用於確定在授權動作時使用哪個策略

1use App\Models\Post;
2use Illuminate\Http\RedirectResponse;
3use Illuminate\Http\Request;
4use Illuminate\Support\Facades\Gate;
5 
6/**
7 * Create a new blog post.
8 *
9 * @throws \Illuminate\Auth\Access\AuthorizationException
10 */
11public function create(Request $request): RedirectResponse
12{
13 Gate::authorize('create', Post::class);
14 
15 // The current user can create blog posts...
16 
17 return redirect('/posts');
18}

透過中介軟體

Laravel 包含一箇中間件,可以在傳入請求到達您的路由或控制器之前授權動作。預設情況下,Illuminate\Auth\Middleware\Authorize 中介軟體可以使用 can 中介軟體別名 附加到路由,該別名由 Laravel 自動註冊。讓我們看一個使用 can 中介軟體來授權使用者可以更新帖子的示例

1use App\Models\Post;
2 
3Route::put('/post/{post}', function (Post $post) {
4 // The current user may update the post...
5})->middleware('can:update,post');

在此示例中,我們向 can 中介軟體傳遞兩個引數。第一個是我們想要授權的動作名稱,第二個是我們想要傳遞給策略方法的路由引數。在這種情況下,因為我們使用的是 隱式模型繫結,所以會將一個 App\Models\Post 模型傳遞給策略方法。如果使用者無權執行給定的動作,中介軟體將返回一個 403 狀態程式碼的 HTTP 響應。

為了方便起見,您還可以使用 can 方法將 can 中介軟體附加到您的路由

1use App\Models\Post;
2 
3Route::put('/post/{post}', function (Post $post) {
4 // The current user may update the post...
5})->can('update', 'post');

如果您使用的是 控制器中介軟體屬性,則可以透過 Authorize 屬性應用 can 中介軟體

1use Illuminate\Routing\Attributes\Controllers\Authorize;
2 
3#[Authorize('update', 'post')]
4public function update(Post $post)
5{
6 // The current user may update the post...
7}

不需要模型的方法

再次說明,一些像 create 這樣的策略方法不需要模型例項。在這些情況下,您可以將類名傳遞給中介軟體。類名將用於確定在授權動作時使用哪個策略

1Route::post('/post', function () {
2 // The current user may create posts...
3})->middleware('can:create,App\Models\Post');

在字串中介軟體定義中指定完整的類名可能會變得很麻煩。因此,您可以選擇使用 can 方法將 can 中介軟體附加到您的路由

1use App\Models\Post;
2 
3Route::post('/post', function () {
4 // The current user may create posts...
5})->can('create', Post::class);

透過 Blade 模板

在編寫 Blade 模板時,您可能希望僅在使用者有權執行給定動作時才顯示頁面的某一部分。例如,您可能希望僅在使用者確實可以更新帖子時才顯示部落格文章的更新表單。在這種情況下,您可以使用 @can@cannot 指令

1@can('update', $post)
2 <!-- The current user can update the post... -->
3@elsecan('create', App\Models\Post::class)
4 <!-- The current user can create new posts... -->
5@else
6 <!-- ... -->
7@endcan
8 
9@cannot('update', $post)
10 <!-- The current user cannot update the post... -->
11@elsecannot('create', App\Models\Post::class)
12 <!-- The current user cannot create new posts... -->
13@endcannot

這些指令是編寫 @if@unless 語句的便捷快捷方式。上面的 @can@cannot 語句等效於以下語句

1@if (Auth::user()->can('update', $post))
2 <!-- The current user can update the post... -->
3@endif
4 
5@unless (Auth::user()->can('update', $post))
6 <!-- The current user cannot update the post... -->
7@endunless

您還可以確定使用者是否有權執行給定動作陣列中的任何動作。要實現這一點,請使用 @canany 指令

1@canany(['update', 'view', 'delete'], $post)
2 <!-- The current user can update, view, or delete the post... -->
3@elsecanany(['create'], \App\Models\Post::class)
4 <!-- The current user can create a post... -->
5@endcanany

不需要模型的方法

像大多數其他授權方法一樣,如果動作不需要模型例項,您可以將類名傳遞給 @can@cannot 指令

1@can('create', App\Models\Post::class)
2 <!-- The current user can create posts... -->
3@endcan
4 
5@cannot('create', App\Models\Post::class)
6 <!-- The current user can't create posts... -->
7@endcannot

提供額外上下文

使用策略授權動作時,可以將陣列作為第二個引數傳遞給各種授權函式和幫助程式。陣列中的第一個元素將用於確定應呼叫哪個策略,而陣列的其餘元素將作為引數傳遞給策略方法,並在進行授權決策時用於提供額外的上下文。例如,考慮以下包含額外 $category 引數的 PostPolicy 方法定義

1/**
2 * Determine if the given post can be updated by the user.
3 */
4public function update(User $user, Post $post, int $category): bool
5{
6 return $user->id === $post->user_id &&
7 $user->canUpdateCategory($category);
8}

當嘗試確定經過身份驗證的使用者是否可以更新給定帖子時,我們可以像這樣呼叫此策略方法

1/**
2 * Update the given blog post.
3 *
4 * @throws \Illuminate\Auth\Access\AuthorizationException
5 */
6public function update(Request $request, Post $post): RedirectResponse
7{
8 Gate::authorize('update', [$post, $request->category]);
9 
10 // The current user can update the blog post...
11 
12 return redirect('/posts');
13}

授權與 Inertia

儘管授權必須始終在伺服器端處理,但提供授權資料給前端應用程式以正確渲染應用程式 UI 通常很方便。Laravel 沒有為向 Inertia 驅動的前端公開授權資訊定義強制性的約定。

但是,如果您使用的是 Laravel 的 Inertia 驅動的 入門套件 之一,您的應用程式已經包含一個 HandleInertiaRequests 中介軟體。在此中介軟體的 share 方法中,您可以返回將提供給應用程式中所有 Inertia 頁面的共享資料。此共享資料可以作為一個方便的位置來定義使用者的授權資訊

1<?php
2 
3namespace App\Http\Middleware;
4 
5use App\Models\Post;
6use Illuminate\Http\Request;
7use Inertia\Middleware;
8 
9class HandleInertiaRequests extends Middleware
10{
11 // ...
12 
13 /**
14 * Define the props that are shared by default.
15 *
16 * @return array<string, mixed>
17 */
18 public function share(Request $request)
19 {
20 return [
21 ...parent::share($request),
22 'auth' => [
23 'user' => $request->user(),
24 'permissions' => [
25 'post' => [
26 'create' => $request->user()->can('create', Post::class),
27 ],
28 ],
29 ],
30 ];
31 }
32}