您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“Laravel Guards怎么使用”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“Laravel Guards怎么使用”吧!
Laravel有一個(gè)最常見的功能,即對持久用戶進(jìn)行身份驗(yàn)證,在這種情況下, 這些功能存儲(chǔ)在任何受支持的數(shù)據(jù)庫 (MySQL, SQLite 等),當(dāng)你考慮到你可以在幾分鐘內(nèi)設(shè)置一個(gè)web應(yīng)用程序并使用忘記的密碼和所有的調(diào)整進(jìn)行用戶身份驗(yàn)證時(shí),這個(gè)東西是令人驚嘆的。當(dāng)你需要更復(fù)雜的東西時(shí)會(huì)發(fā)生什么?
例如,如果您需要擁有自己的身份驗(yàn)證門戶的多個(gè)用戶類型,該怎么辦?這些不同類型的用戶可以是客戶、銷售商和管理員。這樣的機(jī)制可能很快就會(huì)變得非?;靵y,我知道,因?yàn)槲以?jīng)經(jīng)歷過。我們通常預(yù)先計(jì)劃數(shù)據(jù)庫的結(jié)構(gòu),但不構(gòu)建我們的身份驗(yàn)證流程和機(jī)制的樣子。
什么是 Guards?
Laravel 中的 Guards 是一種機(jī)制,您的應(yīng)用程序可以通過它知道某人甚至某事是否經(jīng)過身份驗(yàn)證。當(dāng)我們查看 Laravel 的默認(rèn)安裝時(shí),我們通常會(huì)看到一個(gè)守衛(wèi),即 web。當(dāng)訪問者通過此防護(hù)進(jìn)行身份驗(yàn)證時(shí),任何使用 auth 中間件都將允許用戶通過查看頁面,這是因?yàn)殚_箱即用的默認(rèn)防護(hù)始終是 web。如果一個(gè)人正在瀏覽并且在任何時(shí)候都沒有經(jīng)過身份驗(yàn)證,那么他們在該守衛(wèi)中被稱為訪客。
通常,當(dāng)向 Web 應(yīng)用程序添加額外的防護(hù)時(shí),它會(huì)為 API 提供不同的身份驗(yàn)證機(jī)制,例如用戶令牌。不過,這個(gè)默認(rèn)守衛(wèi)不必是您應(yīng)用程序中唯一的 Web 守衛(wèi)。事實(shí)上,我們可以為不同的用戶類型設(shè)置一個(gè) Guard,即使是那些不使用傳統(tǒng)用戶名和密碼進(jìn)行身份驗(yàn)證的用戶。
如何為 Eloquent 提供程序創(chuàng)建新的 Authenticatable?
為了演示如何創(chuàng)建一個(gè)新的 Authenticatable,我們將使用一個(gè)頁面示例,訂單的客戶可以通過該頁面進(jìn)行身份驗(yàn)證。 客戶只能使用簽名 URL 對應(yīng)用程序進(jìn)行身份驗(yàn)證,一旦通過身份驗(yàn)證,他們就可以執(zhí)行其他操作,例如取消訂單。
首先,我們創(chuàng)建一個(gè)新模型:
php artisan make:model Order
現(xiàn)在,我們需要修改 app/Models/Order.php 中的 Order 模型,添加一些 interfaces 和 traits。 這滿足 Order 模型可用于守衛(wèi)和 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 模型相比,我們可以簡單地?cái)U(kuò)展框架的 User 類,但由于我們不打算使用密碼,所以我們將忽略能夠重置其密碼的模型。
完成此操作后,我們需要將我們的保護(hù)添加到 configs/auth.php 中的 auth 配置中。 因?yàn)槲覀円彩褂貌煌哪P?,所以我們需要?shí)現(xiàn)一個(gè)附加提供程序,我們將其稱為訂單提供程序,由客戶守衛(wèi)使用。
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', // ], ], ];
就是這樣,我們的新守衛(wèi)現(xiàn)在已經(jīng)通過了身份驗(yàn)證,但是我們需要一個(gè)機(jī)制來驗(yàn)證訪問者,而不需要輸入密碼。
身份驗(yàn)證是否需要密碼?
從技術(shù)上講,是的, 身份驗(yàn)證需要密碼,因?yàn)樗荓ighmate\Contracts\Auth\Authenticatable接口的一部分,該接口需要getAuthPassword()的實(shí)現(xiàn)。在前面的示例中,我們使用了Authenticatable特征來提供實(shí)現(xiàn)。不過,只有當(dāng)我們嘗試使用守衛(wèi)的嘗試方法時(shí),才會(huì)使用此代碼,而我們不會(huì)使用此方法。
在這種情況下,我們沒有計(jì)劃通過電子郵件和密碼來驗(yàn)證我們的訂單,所以我們不必?fù)?dān)心這一點(diǎn)。取而代之的是,我們將簡單地創(chuàng)建一個(gè)新的中間件 組件,它將處理來自簽名的URL的身份驗(yàn)證,只有我們的應(yīng)用程序才能生成該URL供賣家提供給客戶。
首先,我們將在routes/web.php中為我們的訂單設(shè)置一個(gè)示例路由。
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', ]);
請注意,我們已經(jīng)添加了一個(gè)經(jīng)過身份驗(yàn)證的中間件。它還不存在,所以我們必須創(chuàng)建一個(gè)并將其添加到http內(nèi)核。我們可以使用以下命令創(chuàng)建中間件:
php artisan make:middleware AuthenticateWhenRequestIsSigned
這將創(chuàng)建app/Http/Middleware/AuthenticateWhenRequestIsSigned.php文件,我們可以編輯該文件。我們將向Handle方法添加兩個(gè)參數(shù),這兩個(gè)參數(shù)將是要從路由和我們想要進(jìn)行身份驗(yàn)證的守衛(wèi)中使用的參數(shù)名稱。然后,Handle方法的代碼非常簡單,如果請求已簽名,則使用Order參數(shù)中的ID值對客戶進(jìn)行身份驗(yàn)證。
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); } }
現(xiàn)在我們已經(jīng)創(chuàng)建了中間件,我們需要在內(nèi)核中注冊它。
Kernel.php
<?php namespace App\Http; use Illuminate\Foundation\Http\Kernel as HttpKernel; class Kernel extends HttpKernel { // Http內(nèi)核的其余部分 /** * 應(yīng)用程序的路由中間件。 * * 這些中間件可以分配到組中,也可以單獨(dú)使用。 * * @var array */ protected $routeMiddleware = [ // 數(shù)組的其余部分 'auth.signed' => \App\Http\Middleware\AuthenticateWhenRequestIsSigned::class, // 數(shù)組的其余部分 ]; // Http內(nèi)核的其余部分 }
這樣做不會(huì)使中間件工作,因?yàn)槲覀冞€將身份驗(yàn)證中間件用于我們的路由,這意味著身份驗(yàn)證簽名的中間件永遠(yuǎn)不會(huì)執(zhí)行,因?yàn)樯矸蒡?yàn)證中間件具有優(yōu)先級,并且將在簽名中間件有機(jī)會(huì)對客戶進(jìn)行身份驗(yàn)證之前終止請求。
要解決這個(gè)問題,我們只需要向內(nèi)核添加一個(gè)額外的數(shù)組,以設(shè)置在會(huì)話啟動(dòng)中間件之后運(yùn)行的身份驗(yàn)證簽名中間件的優(yōu)先級。
Kernel.php
<?php namespace App\Http; use Illuminate\Foundation\Http\Kernel as HttpKernel; class Kernel extends HttpKernel { // HTTP內(nèi)核的其余部分 /** * 中間件的優(yōu)先級排序列表。 * * 強(qiáng)制非全局中間件始終處于給定順序。 * * @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, ]; }
我們可以通過向內(nèi)核添加midlewarePriority屬性來實(shí)現(xiàn)這一點(diǎn),覆蓋父級Kernel。在AuthenticatesRequests中間件和StartSession中間件之前這樣做意味著,當(dāng)URL中提供有效簽名時(shí),中間件可以對客戶進(jìn)行身份驗(yàn)證。
現(xiàn)在,每當(dāng)訪問者使用帶有有效簽名的url登陸該頁面時(shí),他們將通過我們的守衛(wèi)進(jìn)行身份驗(yàn)證,并能夠在沒有簽名的情況下重新訪問該url,直到他們的會(huì)話超時(shí)。不過,這仍然有一個(gè)問題,任何這樣做的客戶也不僅能夠查看他們的訂單,還可以通過簡單地更改URL中的id來查看任何訂單。請記住,Authentication不是Authorization,這意味著為了保護(hù)客戶的其他訂單,我們需要添加一些授權(quán)。
我們?nèi)绾伪Wo(hù)客戶只看到一個(gè)訂單?
這是一個(gè)相當(dāng)簡單的程序。我們現(xiàn)在只需要一個(gè)策略,但在本例中,我們需要使用guard參數(shù)作為policy make命令的一部分。這將允許我們生成我們需要的大部分代碼。
php artisan make:policy --guard customer --model App/Models/Order CustomerOrderPolicy
現(xiàn)在,由于模型和可驗(yàn)證的匹配,我們需要重命名幾個(gè)方法的參數(shù),并為這些方法分配一個(gè)返回值,這將允許訂單只查看和更新它自己。我們需要繼續(xù)編輯app/policies/customerOrderPolicy.php。我們實(shí)現(xiàn)了用于updating和viewing單個(gè)訂單的方法,其余的可以返回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; } }
一旦我們完成了這一點(diǎn),我們只需要注冊策略并將中間件添加到路由中?,F(xiàn)在,當(dāng)經(jīng)過身份驗(yàn)證的用戶試圖訪問除他們自己的訂單之外的任何訂單時(shí),他們都將失敗。這樣,我們就通過對用戶的身份驗(yàn)證和授權(quán)保護(hù)了應(yīng)用程序。
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 { /** * 應(yīng)用程序的策略映射. * * @var array */ protected $policies = [ Order::class => CustomerOrderPolicy::class, ]; // AuthServiceProvider 的其余部分 }
現(xiàn)在,我們通過配置路由查看訂單的策略。
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 重命名為更具描述性的東西有多難?
只有當(dāng)我們也有一名稱為賣家的守衛(wèi)時(shí),讓一名稱為客戶的守衛(wèi)才真正有意義,他們?nèi)匀粫?huì)使用電子郵件和密碼進(jìn)行身份驗(yàn)證,為客戶生成訂單。我們已經(jīng)有了 web 守衛(wèi),但這并不是真正適合所有的 web 用戶,而是為賣家準(zhǔn)備的,所以我們會(huì)相應(yīng)地給它命名。
重命名默認(rèn)守衛(wèi)可能會(huì)變得很棘手,特別是在其他中間件和包(如Laravel Sanctum和Fortify)將按名稱使用 Web 守衛(wèi)的情況下。幸運(yùn)的是,這兩個(gè)包都有配置選項(xiàng),可以輕松地更改這一點(diǎn)。
首先,我們必須編輯 configs/auth.php 以擁有一個(gè)名為賣家的守衛(wèi)。然后,我們還需要更新默認(rèn)值以反映名稱更改。
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 那么每個(gè)配置都需要設(shè)置一個(gè) guard ,該值將為這些包配置保護(hù). 之后就可以使用了. 需要用 auth:seller 替代 auth:web 更新路由 。
到此,相信大家對“Laravel Guards怎么使用”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。