Laravel: Ủy quyền (Authorization)

Các khóa học qua video:
Python SQL Server PHP C# Lập trình C Java HTML5-CSS3-JavaScript
Học trên YouTube <76K/tháng. Đăng ký Hội viên
Viết nhanh hơn - Học tốt hơn
Giải phóng thời gian, khai phóng năng lực

 

Giới thiệu

Ngoài việc cung cấp các dịch vụ xác thực tích hợp , Laravel cũng cung cấp một cách đơn giản để ủy quyền các hành động của người dùng đối với một tài nguyên nhất định. Ví dụ: ngay cả khi người dùng được xác thực, họ có thể không được phép cập nhật hoặc xóa một số mô hình Eloquent hoặc bản ghi cơ sở dữ liệu do ứng dụng của bạn quản lý. Các tính năng ủy quyền của Laravel cung cấp một cách dễ dàng, có tổ chức để quản lý các loại kiểm tra ủy quyền này.

Laravel cung cấp hai cách chính để ủy quyền hành động: cổng và chính sách . Hãy nghĩ về các cổng và chính sách như các tuyến đường và bộ điều khiển. Gates cung cấp một cách tiếp cận đơn giản, dựa trên đóng để ủy quyền trong khi các chính sách, như bộ điều khiển, logic nhóm xung quanh một mô hình hoặc tài nguyên cụ thể. Trong tài liệu này, trước tiên chúng ta sẽ khám phá các cổng và sau đó xem xét các chính sách.

Bạn không cần phải lựa chọn giữa việc sử dụng độc quyền các cổng hoặc sử dụng riêng các chính sách khi xây dựng một ứng dụng. Hầu hết các ứng dụng rất có thể sẽ chứa một số hỗn hợp các cổng và chính sách, và điều đó hoàn toàn ổn! Gates áp dụng nhiều nhất cho các hành động không liên quan đến bất kỳ mô hình hoặc tài nguyên nào, chẳng hạn như xem bảng điều khiển dành cho quản trị viên. Ngược lại, các chính sách nên được sử dụng khi bạn muốn ủy quyền một hành động cho một mô hình hoặc tài nguyên cụ thể.

 

Cổng

 

Viết Gates

 

Cổng là một cách tuyệt vời để tìm hiểu những điều cơ bản về các tính năng ủy quyền của Laravel; tuy nhiên, khi xây dựng các ứng dụng Laravel mạnh mẽ, bạn nên cân nhắc sử dụng các chính sách để tổ chức các quy tắc ủy quyền của mình.

 

Các cổng chỉ đơn giản là các chốt xác định xem người dùng có được phép thực hiện một hành động nhất định hay không. Thông thường, các cổng được định nghĩa trong bootphương thức của App\Providers\AuthServiceProviderlớp bằng cách sử dụng Gatemặt tiền. Gates luôn nhận một cá thể người dùng làm đối số đầu tiên của họ và có thể tùy ý nhận các đối số bổ sung, chẳng hạn như một mô hình Eloquent có liên quan.

Trong ví dụ này, chúng tôi sẽ xác định một cổng để xác định xem người dùng có thể cập nhật một App\Models\Postmô hình nhất định hay không . Cổng sẽ thực hiện điều này bằng cách so sánh người dùng idvới user_idngười dùng đã tạo bài đăng:

use App\Models\Post;
use App\Models\User;
use Illuminate\Support\Facades\Gate;

/**
 * Register any authentication / authorization services.
 *
 * @return void
 */
public function boot()
{
    $this->registerPolicies();

    Gate::define('update-post', function (User $user, Post $post) {
        return $user->id === $post->user_id;
    });
}

Giống như bộ điều khiển, các cổng cũng có thể được xác định bằng cách sử dụng mảng gọi lại lớp:

use App\Policies\PostPolicy;
use Illuminate\Support\Facades\Gate;

/**
 * Register any authentication / authorization services.
 *
 * @return void
 */
public function boot()
{
    $this->registerPolicies();

    Gate::define('update-post', [PostPolicy::class, 'update']);
}

 

Cấp phép Hành động

Để cho phép một hành động bằng cách sử dụng cổng, bạn nên sử dụng allowshoặc deniescác phương pháp được cung cấp bởi Gatemặt tiền. Lưu ý rằng bạn không bắt buộc phải chuyển người dùng hiện đã được xác thực đến các phương thức này. Laravel sẽ tự động xử lý việc đưa người dùng vào cổng đóng. Thông thường, bạn nên gọi các phương thức ủy quyền cổng trong bộ điều khiển của ứng dụng trước khi thực hiện một hành động yêu cầu ủy quyền:

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Models\Post;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;

class PostController extends Controller
{
    /**
     * Update the given post.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Models\Post  $post
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Post $post)
    {
        if (! Gate::allows('update-post', $post)) {
            abort(403);
        }

        // Update the post...
    }
}

Nếu bạn muốn xác định xem một người dùng khác với người dùng hiện đã được xác thực có được ủy quyền để thực hiện một hành động hay không, bạn có thể sử dụng forUserphương pháp trên Gatemặt tiền:

if (Gate::forUser($user)->allows('update-post', $post)) {
    // The user can update the post...
}

if (Gate::forUser($user)->denies('update-post', $post)) {
    // The user can't update the post...
}

Bạn có thể cho phép nhiều hành động cùng một lúc bằng cách sử dụng anyhoặc nonecác phương pháp:

if (Gate::any(['update-post', 'delete-post'], $post)) {
    // The user can update or delete the post...
}

if (Gate::none(['update-post', 'delete-post'], $post)) {
    // The user can't update or delete the post...
}

 

Cho phép hoặc Bỏ qua các trường hợp ngoại lệ

Nếu bạn muốn cố gắng cho phép một hành động và tự động ném Illuminate\Auth\Access\AuthorizationExceptionnếu người dùng không được phép thực hiện hành động đã cho, bạn có thể sử dụng phương thức Gatecủa mặt tiền authorize. Các phiên bản của AuthorizationExceptionđược tự động chuyển đổi thành phản hồi HTTP 403 bởi trình xử lý ngoại lệ của Laravel:

Gate::authorize('update-post', $post);

// The action is authorized...

 

Cung cấp ngữ cảnh bổ sung

Các phương pháp cửa cho khả năng ủy quyền ( allowsdeniescheckanynoneauthorizecancannot) và ủy quyền chỉ thị Blade ( @can@cannot@canany) có thể nhận được một mảng như là đối số thứ hai của họ. Các phần tử mảng này được truyền dưới dạng tham số cho quá trình đóng cổng và có thể được sử dụng cho ngữ cảnh bổ sung khi đưa ra quyết định ủy quyền:

use App\Models\Category;
use App\Models\User;
use Illuminate\Support\Facades\Gate;

Gate::define('create-post', function (User $user, Category $category, $pinned) {
    if (! $user->canPublishToGroup($category->group)) {
        return false;
    } elseif ($pinned && ! $user->canPinPosts()) {
        return false;
    }

    return true;
});

if (Gate::check('create-post', [$category, $pinned])) {
    // The user can create the post...
}

 

Cổng phản hồi

Cho đến nay, chúng tôi mới chỉ kiểm tra các cổng trả về giá trị boolean đơn giản. Tuy nhiên, đôi khi bạn có thể muốn trả lại phản hồi chi tiết hơn, bao gồm cả thông báo lỗi. Để làm như vậy, bạn có thể trả về Illuminate\Auth\Access\Responsetừ cổng của mình:

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('You must be an administrator.');
});

Ngay cả khi bạn trả về một phản hồi ủy quyền từ cổng của mình, Gate::allowsphương thức này vẫn sẽ trả về một giá trị boolean đơn giản; tuy nhiên, bạn có thể sử dụng Gate::inspectphương pháp này để nhận được phản hồi ủy quyền đầy đủ do cổng trả về:

$response = Gate::inspect('edit-settings');

if ($response->allowed()) {
    // The action is authorized...
} else {
    echo $response->message();
}

Khi sử dụng Gate::authorizephương thức ném một AuthorizationExceptionnếu hành động không được ủy quyền, thông báo lỗi được cung cấp bởi phản hồi ủy quyền sẽ được truyền đến phản hồi HTTP:

Gate::authorize('edit-settings');

// The action is authorized...

 

Kiểm tra cổng chặn

Đôi khi, bạn có thể muốn cấp tất cả các khả năng cho một người dùng cụ thể. Bạn có thể sử dụng beforephương pháp này để xác định một quá trình đóng được chạy trước tất cả các lần kiểm tra ủy quyền khác:

use Illuminate\Support\Facades\Gate;

Gate::before(function ($user, $ability) {
    if ($user->isAdministrator()) {
        return true;
    }
});

Nếu việc befoređóng cửa trả về một kết quả không rỗng thì kết quả đó sẽ được coi là kết quả của việc kiểm tra ủy quyền.

Bạn có thể sử dụng afterphương pháp để xác định một đóng sẽ được thực thi sau tất cả các lần kiểm tra ủy quyền khác:

Gate::after(function ($user, $ability, $result, $arguments) {
    if ($user->isAdministrator()) {
        return true;
    }
});

Tương tự như beforephương thức, nếu việc afterđóng trả về một kết quả khác rỗng thì kết quả đó sẽ được coi là kết quả của việc kiểm tra ủy quyền.

 

Tạo chính sách

 

Tạo chính sách

Chính sách là các lớp tổ chức logic ủy quyền xung quanh một mô hình hoặc tài nguyên cụ thể. Ví dụ: nếu ứng dụng của bạn là một blog, bạn có thể có một App\Models\Postmô hình và một mô hình tương ứng App\Policies\PostPolicyđể cho phép người dùng thực hiện các hành động như tạo hoặc cập nhật bài đăng.

Bạn có thể tạo một chính sách bằng make:policylệnh Artisan. Chính sách đã tạo sẽ được đặt trong app/Policiesthư mục. Nếu thư mục này không tồn tại trong ứng dụng của bạn, Laravel sẽ tạo nó cho bạn:

php artisan make:policy PostPolicy

Các make:policylệnh sẽ tạo ra một lớp chính sách rỗng. Nếu bạn muốn tạo một lớp với các phương thức chính sách mẫu liên quan đến việc xem, tạo, cập nhật và xóa tài nguyên, bạn có thể cung cấp một --modeltùy chọn khi thực hiện lệnh:

php artisan make:policy PostPolicy --model=Post

 

Chính sách Đăng ký

Khi lớp chính sách đã được tạo, nó cần được đăng ký. Đăng ký các chính sách là cách chúng tôi có thể thông báo cho Laravel chính sách nào sẽ sử dụng khi cho phép các hành động chống lại một loại mô hình nhất định.

Phần mềm đi App\Providers\AuthServiceProviderkèm với các ứng dụng Laravel mới có chứa một thuộc policiestính ánh xạ các mô hình Eloquent của bạn với các chính sách tương ứng của chúng. Việc đăng ký một chính sách sẽ hướng dẫn Laravel sử dụng chính sách nào khi cho phép các hành động chống lại một mô hình Eloquent nhất định:

<?php

namespace App\Providers;

use App\Models\Post;
use App\Policies\PostPolicy;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        Post::class => PostPolicy::class,
    ];

    /**
     * Register any application authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        //
    }
}

 

Tự động khám phá chính sách

Thay vì đăng ký các chính sách mô hình theo cách thủ công, Laravel có thể tự động khám phá các chính sách miễn là mô hình và chính sách tuân theo các quy ước đặt tên Laravel tiêu chuẩn. Cụ thể, các chính sách phải nằm trong một Policiesthư mục tại hoặc phía trên thư mục chứa các mô hình của bạn. Vì vậy, ví dụ, các mô hình có thể được đặt trong app/Modelsthư mục trong khi các chính sách có thể được đặt trong app/Policiesthư mục. Trong tình huống này, Laravel sẽ kiểm tra các chính sách trong app/Models/Policiesđó app/Policies. Ngoài ra, tên chính sách phải khớp với tên kiểu máy và có một Policyhậu tố. Vì vậy, một Usermô hình sẽ tương ứng với một UserPolicylớp chính sách.

Nếu bạn muốn xác định logic khám phá chính sách của riêng mình, bạn có thể đăng ký lệnh gọi lại khám phá chính sách tùy chỉnh bằng Gate::guessPolicyNamesUsingphương pháp này. Thông thường, phương thức này sẽ được gọi từ bootphương thức của ứng dụng của bạn AuthServiceProvider:

use Illuminate\Support\Facades\Gate;

Gate::guessPolicyNamesUsing(function ($modelClass) {
    // Return the name of the policy class for the given model...
});

 

Bất kỳ chính sách nào được ánh xạ rõ ràng trong của bạn AuthServiceProvidersẽ được ưu tiên hơn bất kỳ chính sách nào có khả năng được phát hiện tự động.

 

 

Viết chính sách

 

Phương pháp chính sách

Khi lớp chính sách đã được đăng ký, bạn có thể thêm các phương thức cho mỗi hành động mà nó cho phép. Ví dụ, chúng ta hãy xác định một updatephương thức trên của chúng ta PostPolicyđể xác định xem một phương thức đã cho App\Models\Usercó thể cập nhật một App\Models\Posttrường hợp nhất định hay không .

Các updatephương pháp sẽ nhận được một Uservà một Poství dụ như các đối số của nó, và phải trả lại truehoặc falsechỉ ra cho dù người dùng được phép cập nhật được Post. Vì vậy, trong ví dụ này, chúng tôi sẽ xác minh rằng người dùng idphù hợp với user_idtrên bài đăng:

<?php

namespace App\Policies;

use App\Models\Post;
use App\Models\User;

class PostPolicy
{
    /**
     * Determine if the given post can be updated by the user.
     *
     * @param  \App\Models\User  $user
     * @param  \App\Models\Post  $post
     * @return bool
     */
    public function update(User $user, Post $post)
    {
        return $user->id === $post->user_id;
    }
}

Bạn có thể tiếp tục xác định các phương pháp bổ sung trên chính sách nếu cần cho các hành động khác nhau mà chính sách cho phép. Ví dụ: bạn có thể xác định viewhoặc deletecác phương thức để cho phép các Posthành động liên quan khác nhau , nhưng hãy nhớ rằng bạn có thể tự do đặt tên cho các phương thức chính sách của mình bất kỳ tên nào bạn thích.

Nếu bạn sử dụng --modeltùy chọn khi tạo chính sách của bạn thông qua giao diện điều khiển Artisan, nó sẽ đã chứa các phương pháp để viewAnyviewcreateupdatedeleterestore, và forceDeletehành động.

 

Tất cả các chính sách được giải quyết thông qua vùng chứa dịch vụ Laravel , cho phép bạn nhập gợi ý bất kỳ phụ thuộc cần thiết nào trong phương thức khởi tạo của chính sách để chúng tự động được đưa vào.

 

 

Phản hồi chính sách

Cho đến nay, chúng tôi mới chỉ kiểm tra các phương thức chính sách trả về các giá trị boolean đơn giản. Tuy nhiên, đôi khi bạn có thể muốn trả lại phản hồi chi tiết hơn, bao gồm cả thông báo lỗi. Để làm như vậy, bạn có thể trả về một Illuminate\Auth\Access\Responsephiên bản từ phương thức chính sách của mình:

use App\Models\Post;
use App\Models\User;
use Illuminate\Auth\Access\Response;

/**
 * Determine if the given post can be updated by the user.
 *
 * @param  \App\Models\User  $user
 * @param  \App\Models\Post  $post
 * @return \Illuminate\Auth\Access\Response
 */
public function update(User $user, Post $post)
{
    return $user->id === $post->user_id
                ? Response::allow()
                : Response::deny('You do not own this post.');
}

Khi trả về phản hồi ủy quyền từ chính sách của bạn, Gate::allowsphương thức sẽ vẫn trả về một giá trị boolean đơn giản; tuy nhiên, bạn có thể sử dụng Gate::inspectphương pháp này để nhận được phản hồi ủy quyền đầy đủ do cổng trả về:

use Illuminate\Support\Facades\Gate;

$response = Gate::inspect('update', $post);

if ($response->allowed()) {
    // The action is authorized...
} else {
    echo $response->message();
}

Khi sử dụng Gate::authorizephương thức ném một AuthorizationExceptionnếu hành động không được ủy quyền, thông báo lỗi được cung cấp bởi phản hồi ủy quyền sẽ được truyền đến phản hồi HTTP:

Gate::authorize('update', $post);

// The action is authorized...

 

Phương pháp không có mô hình

Một số phương thức chính sách chỉ nhận được một phiên bản của người dùng hiện đã được xác thực. Tình huống này là phổ biến nhất khi createcác hành động ủy quyền . Ví dụ: nếu bạn đang tạo blog, bạn có thể muốn xác định xem người dùng có được phép tạo bất kỳ bài đăng nào hay không. Trong những trường hợp này, phương pháp chính sách của bạn chỉ nên nhận được một phiên bản người dùng:

/**
 * Determine if the given user can create posts.
 *
 * @param  \App\Models\User  $user
 * @return bool
 */
public function create(User $user)
{
    return $user->role == 'writer';
}

 

Người dùng khách

Theo mặc định, tất cả các cổng và chính sách tự động trả về falsenếu yêu cầu HTTP đến không được khởi tạo bởi người dùng đã xác thực. Tuy nhiên, bạn có thể cho phép các kiểm tra ủy quyền này đi qua các cổng và chính sách của bạn bằng cách khai báo gợi ý loại "tùy chọn" hoặc cung cấp nullgiá trị mặc định cho định nghĩa đối số người dùng:

<?php

namespace App\Policies;

use App\Models\Post;
use App\Models\User;

class PostPolicy
{
    /**
     * Determine if the given post can be updated by the user.
     *
     * @param  \App\Models\User  $user
     * @param  \App\Models\Post  $post
     * @return bool
     */
    public function update(?User $user, Post $post)
    {
        return optional($user)->id === $post->user_id;
    }
}

 

Bộ lọc chính sách

Đối với một số người dùng nhất định, bạn có thể muốn ủy quyền tất cả các hành động trong một chính sách nhất định. Để thực hiện điều này, hãy xác định một beforephương pháp trên chính sách. Các beforephương pháp sẽ được thực hiện trước khi bất kỳ phương pháp khác về chính sách, tạo cho bạn một cơ hội để cho phép các hành động trước khi phương pháp chính sách nhằm mục đích thực sự gọi. Tính năng này được sử dụng phổ biến nhất để ủy quyền cho quản trị viên ứng dụng thực hiện bất kỳ hành động nào:

use App\Models\User;

/**
 * Perform pre-authorization checks.
 *
 * @param  \App\Models\User  $user
 * @param  string  $ability
 * @return void|bool
 */
public function before(User $user, $ability)
{
    if ($user->isAdministrator()) {
        return true;
    }
}

Nếu bạn muốn từ chối tất cả kiểm tra ủy quyền cho một loại người dùng cụ thể thì bạn có thể quay lại falsetừ beforephương thức này. Nếu nullbị trả lại, kiểm tra ủy quyền sẽ chuyển sang phương thức chính sách.

 

Các beforephương pháp của một lớp chính sách sẽ không được gọi là nếu lớp không chứa một phương thức với một tên phù hợp với tên của khả năng được kiểm tra.

 

 

Cho phép các hành động sử dụng chính sách

 

Qua Mô hình Người dùng

Các App\Models\Usermô hình được bao gồm với ứng dụng Laravel của bạn bao gồm hai phương pháp hữu ích cho phép hoạt động: canvà cannot. Các canvà cannotphương thức nhận được tên của hành động bạn muốn cho phép và mô hình có liên quan. Ví dụ: hãy xác định xem người dùng có được phép cập nhật một App\Models\Postmô hình nhất định hay không . Thông thường, điều này sẽ được thực hiện trong phương thức controller:

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Models\Post;
use Illuminate\Http\Request;

class PostController extends Controller
{
    /**
     * Update the given post.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Models\Post  $post
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Post $post)
    {
        if ($request->user()->cannot('update', $post)) {
            abort(403);
        }

        // Update the post...
    }
}

Nếu một chính sách được đăng ký cho mô hình đã cho, canphương thức sẽ tự động gọi chính sách thích hợp và trả về kết quả boolean. Nếu không có chính sách nào được đăng ký cho mô hình, canphương thức sẽ cố gắng gọi Cổng dựa trên đóng khớp với tên hành động đã cho.

 

Các hành động không yêu cầu mô hình

Hãy nhớ rằng, một số hành động có thể tương ứng với các phương thức chính sách như createvậy không yêu cầu phiên bản mô hình. Trong những trường hợp này, bạn có thể chuyển một tên lớp cho canphương thức. Tên lớp sẽ được sử dụng để xác định chính sách nào sẽ sử dụng khi ủy quyền hành động:

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Models\Post;
use Illuminate\Http\Request;

class PostController extends Controller
{
    /**
     * Create a post.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        if ($request->user()->cannot('create', Post::class)) {
            abort(403);
        }

        // Create the post...
    }
}

 

Thông qua Trình trợ giúp Bộ điều khiển

Ngoài các phương thức hữu ích được cung cấp cho App\Models\Usermô hình, Laravel cung cấp một authorizephương pháp hữu ích cho bất kỳ bộ điều khiển nào của bạn mở rộng App\Http\Controllers\Controllerlớp cơ sở.

Giống như canphương thức, phương thức này chấp nhận tên của hành động bạn muốn cho phép và mô hình có liên quan. Nếu hành động không được ủy quyền, authorizephương thức sẽ ném một Illuminate\Auth\Access\AuthorizationExceptionngoại lệ mà trình xử lý ngoại lệ Laravel sẽ tự động chuyển đổi thành phản hồi HTTP với mã trạng thái 403:

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Models\Post;
use Illuminate\Http\Request;

class PostController extends Controller
{
    /**
     * Update the given blog post.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Models\Post  $post
     * @return \Illuminate\Http\Response
     *
     * @throws \Illuminate\Auth\Access\AuthorizationException
     */
    public function update(Request $request, Post $post)
    {
        $this->authorize('update', $post);

        // The current user can update the blog post...
    }
}

 

Các hành động không yêu cầu mô hình

Như đã thảo luận trước đây, một số phương pháp chính sách như createkhông yêu cầu phiên bản mô hình. Trong những tình huống này, bạn nên chuyển một tên lớp cho authorizephương thức. Tên lớp sẽ được sử dụng để xác định chính sách nào sẽ sử dụng khi ủy quyền hành động:

use App\Models\Post;
use Illuminate\Http\Request;

/**
 * Create a new blog post.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Illuminate\Http\Response
 *
 * @throws \Illuminate\Auth\Access\AuthorizationException
 */
public function create(Request $request)
{
    $this->authorize('create', Post::class);

    // The current user can create blog posts...
}

 

Cấp quyền cho bộ điều khiển tài nguyên

Nếu bạn đang sử dụng bộ điều khiển tài nguyên , bạn có thể sử dụng authorizeResourcephương thức trong phương thức khởi tạo của bộ điều khiển. Phương thức này sẽ đính kèm các canđịnh nghĩa phần mềm trung gian thích hợp vào các phương thức của bộ điều khiển tài nguyên.

Các authorizeResourcephương pháp chấp nhận tên lớp của mô hình như là đối số đầu tiên của mình, và tên của tham số đường / yêu cầu sẽ chứa ID của mô hình như là đối số thứ hai. Bạn nên đảm bảo rằng bộ điều khiển tài nguyên của bạn được tạo bằng cách sử dụng --modelcờ để nó có các chữ ký phương thức và gợi ý kiểu cần thiết:

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Models\Post;
use Illuminate\Http\Request;

class PostController extends Controller
{
    /**
     * Create the controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->authorizeResource(Post::class, 'post');
    }
}

Các phương thức bộ điều khiển sau sẽ được ánh xạ tới phương thức chính sách tương ứng của chúng. Khi các yêu cầu được chuyển đến phương thức bộ điều khiển đã cho, phương thức chính sách tương ứng sẽ tự động được gọi trước khi phương thức bộ điều khiển được thực thi:

Phương pháp điều khiển Phương pháp chính sách
mục lục viewAny
chỉ quan điểm
tạo ra tạo ra
cửa hàng tạo ra
chỉnh sửa cập nhật
cập nhật cập nhật
hủy hoại xóa bỏ

 

Bạn có thể sử dụng các make:policylệnh với các --modeltùy chọn để nhanh chóng tạo ra một lớp học chính sách đối với một mô hình đưa ra: php artisan make:policy PostPolicy --model=Post.

 

 

Qua phần mềm trung gian

Laravel bao gồm một phần mềm trung gian có thể cho phép các hành động trước khi yêu cầu đến thậm chí đến được các tuyến đường hoặc bộ điều khiển của bạn. Theo mặc định, Illuminate\Auth\Middleware\Authorizephần mềm trung gian được gán cankhóa trong App\Http\Kernellớp của bạn . Hãy cùng khám phá một ví dụ về việc sử dụng canphần mềm trung gian để cho phép người dùng có thể cập nhật bài đăng:

use App\Models\Post;

Route::put('/post/{post}', function (Post $post) {
    // The current user may update the post...
})->middleware('can:update,post');

Trong ví dụ này, chúng tôi đang chuyển canhai đối số của phần mềm trung gian. Đầu tiên là tên của hành động mà chúng tôi muốn cho phép và thứ hai là tham số tuyến đường mà chúng tôi muốn chuyển cho phương thức chính sách. Trong trường hợp này, vì chúng ta đang sử dụng ràng buộc mô hình ngầm định , một App\Models\Postmô hình sẽ được chuyển cho phương thức chính sách. Nếu người dùng không được phép thực hiện hành động đã cho, phản hồi HTTP với mã trạng thái 403 sẽ được phần mềm trung gian trả về.

 

Các hành động không yêu cầu mô hình

Một lần nữa, một số phương pháp chính sách như createkhông yêu cầu một cá thể mô hình. Trong những tình huống này, bạn có thể chuyển tên lớp cho phần mềm trung gian. Tên lớp sẽ được sử dụng để xác định chính sách nào sẽ sử dụng khi ủy quyền hành động:

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

 

Qua các mẫu Blade

Khi viết các mẫu Blade, bạn có thể muốn hiển thị một phần của trang chỉ khi người dùng được phép thực hiện một hành động nhất định. Ví dụ: bạn có thể muốn hiển thị biểu mẫu cập nhật cho một bài đăng trên blog chỉ khi người dùng thực sự có thể cập nhật bài đăng đó. Trong trường hợp này, bạn có thể sử dụng các lệnh @canvà @cannot:

@can('update', $post)
    <!-- The current user can update the post... -->
@elsecan('create', App\Models\Post::class)
    <!-- The current user can create new posts... -->
@else
    <!-- ... -->
@endcan

@cannot('update', $post)
    <!-- The current user cannot update the post... -->
@elsecannot('create', App\Models\Post::class)
    <!-- The current user cannot create new posts... -->
@endcannot

Các chỉ thị này là các phím tắt thuận tiện cho việc viết @ifvà các @unlesscâu lệnh. Các câu lệnh @canvà @cannotở trên tương đương với các câu lệnh sau:

@if (Auth::user()->can('update', $post))
    <!-- The current user can update the post... -->
@endif

@unless (Auth::user()->can('update', $post))
    <!-- The current user cannot update the post... -->
@endunless

Bạn cũng có thể xác định xem người dùng có được phép thực hiện bất kỳ hành động nào từ một loạt các hành động nhất định hay không. Để thực hiện điều này, hãy sử dụng lệnh @canany:

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

 

Các hành động không yêu cầu mô hình

Giống như hầu hết các phương thức ủy quyền khác, bạn có thể chuyển một tên lớp cho @canvà các @cannotchỉ thị nếu hành động không yêu cầu phiên bản mô hình:

@can('create', App\Models\Post::class)
    <!-- The current user can create posts... -->
@endcan

@cannot('create', App\Models\Post::class)
    <!-- The current user can't create posts... -->
@endcannot

 

Cung cấp ngữ cảnh bổ sung

Khi ủy quyền các hành động bằng chính sách, bạn có thể chuyển một mảng làm đối số thứ hai cho các hàm và trình trợ giúp ủy quyền khác nhau. Phần tử đầu tiên trong mảng sẽ được sử dụng để xác định chính sách nào sẽ được gọi, trong khi phần tử còn lại của mảng được chuyển dưới dạng tham số cho phương thức chính sách và có thể được sử dụng cho ngữ cảnh bổ sung khi đưa ra quyết định ủy quyền. Ví dụ: hãy xem xét PostPolicyđịnh nghĩa phương thức sau có chứa một $categorytham số bổ sung :

/**
 * Determine if the given post can be updated by the user.
 *
 * @param  \App\Models\User  $user
 * @param  \App\Models\Post  $post
 * @param  int  $category
 * @return bool
 */
public function update(User $user, Post $post, int $category)
{
    return $user->id === $post->user_id &&
           $user->canUpdateCategory($category);
}

Khi cố gắng xác định xem người dùng đã xác thực có thể cập nhật một bài đăng nhất định hay không, chúng tôi có thể gọi phương thức chính sách này như sau:

/**
 * Update the given blog post.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \App\Models\Post  $post
 * @return \Illuminate\Http\Response
 *
 * @throws \Illuminate\Auth\Access\AuthorizationException
 */
public function update(Request $request, Post $post)
{
    $this->authorize('update', [$post, $request->category]);

    // The current user can update the blog post...
}
» Tiếp: Redis
« Trước: Thông báo (Notifications)
Các khóa học qua video:
Python SQL Server PHP C# Lập trình C Java HTML5-CSS3-JavaScript
Học trên YouTube <76K/tháng. Đăng ký Hội viên
Viết nhanh hơn - Học tốt hơn
Giải phóng thời gian, khai phóng năng lực
Copied !!!