溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Laravel Guards怎么使用

發(fā)布時(shí)間:2021-12-07 16:11:09 來源:億速云 閱讀:165 作者:iii 欄目:編程語言

本篇內(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 模型,添加一些 interfacestraits。 這滿足 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)了用于updatingviewing單個(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',
        // ],
    ],
];

如果我們還使用 FortifySanctum 那么每個(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í)!

向AI問一下細(xì)節(jié)

免責(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)容。

AI