您好,登錄后才能下訂單哦!
本篇內容主要講解“Laravel Guards怎么使用”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Laravel Guards怎么使用”吧!
Laravel有一個最常見的功能,即對持久用戶進行身份驗證,在這種情況下, 這些功能存儲在任何受支持的數據庫 (MySQL, SQLite 等),當你考慮到你可以在幾分鐘內設置一個web應用程序并使用忘記的密碼和所有的調整進行用戶身份驗證時,這個東西是令人驚嘆的。當你需要更復雜的東西時會發生什么?
例如,如果您需要擁有自己的身份驗證門戶的多個用戶類型,該怎么辦?這些不同類型的用戶可以是客戶、銷售商和管理員。這樣的機制可能很快就會變得非常混亂,我知道,因為我曾經經歷過。我們通常預先計劃數據庫的結構,但不構建我們的身份驗證流程和機制的樣子。
什么是 Guards?
Laravel 中的 Guards 是一種機制,您的應用程序可以通過它知道某人甚至某事是否經過身份驗證。當我們查看 Laravel 的默認安裝時,我們通常會看到一個守衛,即 web。當訪問者通過此防護進行身份驗證時,任何使用 auth 中間件都將允許用戶通過查看頁面,這是因為開箱即用的默認防護始終是 web。如果一個人正在瀏覽并且在任何時候都沒有經過身份驗證,那么他們在該守衛中被稱為訪客。
通常,當向 Web 應用程序添加額外的防護時,它會為 API 提供不同的身份驗證機制,例如用戶令牌。不過,這個默認守衛不必是您應用程序中唯一的 Web 守衛。事實上,我們可以為不同的用戶類型設置一個 Guard,即使是那些不使用傳統用戶名和密碼進行身份驗證的用戶。
如何為 Eloquent 提供程序創建新的 Authenticatable?
為了演示如何創建一個新的 Authenticatable,我們將使用一個頁面示例,訂單的客戶可以通過該頁面進行身份驗證。 客戶只能使用簽名 URL 對應用程序進行身份驗證,一旦通過身份驗證,他們就可以執行其他操作,例如取消訂單。
首先,我們創建一個新模型:
php artisan make:model Order
現在,我們需要修改 app/Models/Order.php 中的 Order 模型,添加一些 interfaces 和 traits。 這滿足 Order 模型可用于守衛和 Eloquent 提供者類型。
Order.php
<?php namespace App\Models; use Illuminate\Auth\Authenticatable; use Illuminate\Auth\MustVerifyEmail; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Foundation\Auth\Access\Authorizable; class Order extends Model implements AuthenticatableContract, AuthorizableContract { use Authenticatable; use Authorizable; use MustVerifyEmail; public function user(): BelongsTo { return $this->belongsTo(User::class); } }
請注意,與開箱即用的 User 模型相比,我們可以簡單地擴展框架的 User 類,但由于我們不打算使用密碼,所以我們將忽略能夠重置其密碼的模型。
完成此操作后,我們需要將我們的保護添加到 configs/auth.php 中的 auth 配置中。 因為我們也使用不同的模型,所以我們需要實現一個附加提供程序,我們將其稱為訂單提供程序,由客戶守衛使用。
auth.php
<?php return [ // auth.php 配置的其余部分 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'customer' => [ 'driver' => 'session', 'provider' => 'orders', ], ], // auth.php 配置的其余部分 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\Models\User::class, ], 'orders' => [ 'driver' => 'eloquent', 'model' => App\Models\Order::class, ], // 'users' => [ // 'driver' => 'database', // 'table' => 'users', // ], ], ];
就是這樣,我們的新守衛現在已經通過了身份驗證,但是我們需要一個機制來驗證訪問者,而不需要輸入密碼。
身份驗證是否需要密碼?
從技術上講,是的, 身份驗證需要密碼,因為它是Lighmate\Contracts\Auth\Authenticatable接口的一部分,該接口需要getAuthPassword()的實現。在前面的示例中,我們使用了Authenticatable特征來提供實現。不過,只有當我們嘗試使用守衛的嘗試方法時,才會使用此代碼,而我們不會使用此方法。
在這種情況下,我們沒有計劃通過電子郵件和密碼來驗證我們的訂單,所以我們不必擔心這一點。取而代之的是,我們將簡單地創建一個新的中間件 組件,它將處理來自簽名的URL的身份驗證,只有我們的應用程序才能生成該URL供賣家提供給客戶。
首先,我們將在routes/web.php中為我們的訂單設置一個示例路由。
web.php
<?php use Illuminate\Support\Facades\Route; Route::get('order/{order}', function (\App\Models\Order $order) { return view('order.view', ['order' => $order]); }) ->name('order.view') ->middleware([ 'auth.signed:order,customer', 'auth:customer,seller', ]);
請注意,我們已經添加了一個經過身份驗證的中間件。它還不存在,所以我們必須創建一個并將其添加到http內核。我們可以使用以下命令創建中間件:
php artisan make:middleware AuthenticateWhenRequestIsSigned
這將創建app/Http/Middleware/AuthenticateWhenRequestIsSigned.php文件,我們可以編輯該文件。我們將向Handle方法添加兩個參數,這兩個參數將是要從路由和我們想要進行身份驗證的守衛中使用的參數名稱。然后,Handle方法的代碼非常簡單,如果請求已簽名,則使用Order參數中的ID值對客戶進行身份驗證。
AuthenticateWhenRequestIsSigned.php
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; class AuthenticateWhenRequestIsSigned { public function handle(Request $request, Closure $next, string $parameterName, string $guard = null) { if ($request->hasValidSignature()) { if (Auth::guard($guard)->check()) { Auth::guard($guard)->logout(); } Auth::guard($guard)->loginUsingId($request->route()->parameter($parameterName)); } return $next($request); } }
現在我們已經創建了中間件,我們需要在內核中注冊它。
Kernel.php
<?php namespace App\Http; use Illuminate\Foundation\Http\Kernel as HttpKernel; class Kernel extends HttpKernel { // Http內核的其余部分 /** * 應用程序的路由中間件。 * * 這些中間件可以分配到組中,也可以單獨使用。 * * @var array */ protected $routeMiddleware = [ // 數組的其余部分 'auth.signed' => \App\Http\Middleware\AuthenticateWhenRequestIsSigned::class, // 數組的其余部分 ]; // Http內核的其余部分 }
這樣做不會使中間件工作,因為我們還將身份驗證中間件用于我們的路由,這意味著身份驗證簽名的中間件永遠不會執行,因為身份驗證中間件具有優先級,并且將在簽名中間件有機會對客戶進行身份驗證之前終止請求。
要解決這個問題,我們只需要向內核添加一個額外的數組,以設置在會話啟動中間件之后運行的身份驗證簽名中間件的優先級。
Kernel.php
<?php namespace App\Http; use Illuminate\Foundation\Http\Kernel as HttpKernel; class Kernel extends HttpKernel { // HTTP內核的其余部分 /** * 中間件的優先級排序列表。 * * 強制非全局中間件始終處于給定順序。 * * @var string[] */ protected $middlewarePriority = [ \Illuminate\Cookie\Middleware\EncryptCookies::class, \Illuminate\Session\Middleware\StartSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\AuthenticateWhenRequestIsSigned::class, \Illuminate\Contracts\Auth\Middleware\AuthenticatesRequests::class, \Illuminate\Routing\Middleware\ThrottleRequests::class, \Illuminate\Routing\Middleware\ThrottleRequestsWithRedis::class, \Illuminate\Session\Middleware\AuthenticateSession::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, \Illuminate\Auth\Middleware\Authorize::class, ]; }
我們可以通過向內核添加midlewarePriority屬性來實現這一點,覆蓋父級Kernel。在AuthenticatesRequests中間件和StartSession中間件之前這樣做意味著,當URL中提供有效簽名時,中間件可以對客戶進行身份驗證。
現在,每當訪問者使用帶有有效簽名的url登陸該頁面時,他們將通過我們的守衛進行身份驗證,并能夠在沒有簽名的情況下重新訪問該url,直到他們的會話超時。不過,這仍然有一個問題,任何這樣做的客戶也不僅能夠查看他們的訂單,還可以通過簡單地更改URL中的id來查看任何訂單。請記住,Authentication不是Authorization,這意味著為了保護客戶的其他訂單,我們需要添加一些授權。
我們如何保護客戶只看到一個訂單?
這是一個相當簡單的程序。我們現在只需要一個策略,但在本例中,我們需要使用guard參數作為policy make命令的一部分。這將允許我們生成我們需要的大部分代碼。
php artisan make:policy --guard customer --model App/Models/Order CustomerOrderPolicy
現在,由于模型和可驗證的匹配,我們需要重命名幾個方法的參數,并為這些方法分配一個返回值,這將允許訂單只查看和更新它自己。我們需要繼續編輯app/policies/customerOrderPolicy.php。我們實現了用于updating和viewing單個訂單的方法,其余的可以返回false。
CustomerOrderPolicy.php
<?php namespace App\Policies; use App\Models\Order; use Illuminate\Auth\Access\HandlesAuthorization; class CustomerOrderPolicy { use HandlesAuthorization; public function viewAny(Order $order) { return false; } public function view(Order $customer, Order $order) { return $customer->is($order); } public function create(Order $order) { return false; } public function update(Order $customer, Order $order) { return $customer->is($order); } public function delete(Order $customer, Order $order) { return false; } public function restore(Order $customer, Order $order) { return false; } public function forceDelete(Order $customer, Order $order) { return false; } }
一旦我們完成了這一點,我們只需要注冊策略并將中間件添加到路由中。現在,當經過身份驗證的用戶試圖訪問除他們自己的訂單之外的任何訂單時,他們都將失敗。這樣,我們就通過對用戶的身份驗證和授權保護了應用程序。
AuthServiceProvider.php
<?php namespace App\Providers; use App\Models\Order; use App\Policies\CustomerOrderPolicy; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; use Illuminate\Support\Facades\Gate; class AuthServiceProvider extends ServiceProvider { /** * 應用程序的策略映射. * * @var array */ protected $policies = [ Order::class => CustomerOrderPolicy::class, ]; // AuthServiceProvider 的其余部分 }
現在,我們通過配置路由查看訂單的策略。
web.php
<?php use Illuminate\Support\Facades\Route; Route::get('order/{order}', function (\App\Models\Order $order) { return view('order.view', ['order' => $order]); }) ->name('order.view') ->middleware([ 'auth.signed:order,customer', 'auth:customer,seller', 'can:view,order' ]);
將 Web Guard 重命名為更具描述性的東西有多難?
只有當我們也有一名稱為賣家的守衛時,讓一名稱為客戶的守衛才真正有意義,他們仍然會使用電子郵件和密碼進行身份驗證,為客戶生成訂單。我們已經有了 web 守衛,但這并不是真正適合所有的 web 用戶,而是為賣家準備的,所以我們會相應地給它命名。
重命名默認守衛可能會變得很棘手,特別是在其他中間件和包(如Laravel Sanctum和Fortify)將按名稱使用 Web 守衛的情況下。幸運的是,這兩個包都有配置選項,可以輕松地更改這一點。
首先,我們必須編輯 configs/auth.php 以擁有一個名為賣家的守衛。然后,我們還需要更新默認值以反映名稱更改。
auth.php
<?php return [ // auth.php 其余的配置部分 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'customer' => [ 'driver' => 'session', 'provider' => 'orders', ], ], // auth.php 其余的配置部分 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\Models\User::class, ], 'orders' => [ 'driver' => 'eloquent', 'model' => App\Models\Order::class, ], // 'users' => [ // 'driver' => 'database', // 'table' => 'users', // ], ], ];
如果我們還使用 Fortify 和 Sanctum 那么每個配置都需要設置一個 guard ,該值將為這些包配置保護. 之后就可以使用了. 需要用 auth:seller 替代 auth:web 更新路由 。
到此,相信大家對“Laravel Guards怎么使用”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。