Laravel: Ủy quyền (Authorization)
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 boot
phương thức của App\Providers\AuthServiceProvider
lớp bằng cách sử dụng Gate
mặ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\Post
mô 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 id
với user_id
ngườ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 allows
hoặc denies
các phương pháp được cung cấp bởi Gate
mặ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 forUser
phương pháp trên Gate
mặ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 any
hoặc none
cá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\AuthorizationException
nế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 Gate
củ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 ( allows
, denies
, check
, any
, none
, authorize
, can
, cannot
) 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\Response
từ 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::allows
phươ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::inspect
phươ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::authorize
phương thức ném một AuthorizationException
nế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 before
phươ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 after
phươ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ư before
phươ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\Post
mô 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:policy
lệnh Artisan. Chính sách đã tạo sẽ được đặt trong app/Policies
thư 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:policy
lệ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 --model
tù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\AuthServiceProvider
kèm với các ứng dụng Laravel mới có chứa một thuộc policies
tí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 Policies
thư 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/Models
thư mục trong khi các chính sách có thể được đặt trong app/Policies
thư 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 Policy
hậu tố. Vì vậy, một User
mô hình sẽ tương ứng với một UserPolicy
lớ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::guessPolicyNamesUsing
phương pháp này. Thông thường, phương thức này sẽ được gọi từ boot
phươ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
AuthServiceProvider
sẽ đượ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 update
phương thức trên của chúng ta PostPolicy
để xác định xem một phương thức đã cho App\Models\User
có thể cập nhật một App\Models\Post
trường hợp nhất định hay không .
Các update
phương pháp sẽ nhận được một User
và một Post
ví dụ như các đối số của nó, và phải trả lại true
hoặc false
chỉ 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 id
phù hợp với user_id
trê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 view
hoặc delete
các phương thức để cho phép các Post
hà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 --model
tù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 để viewAny
, view
, create
, update
, delete
, restore
, và forceDelete
hà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\Response
phiê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::allows
phươ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::inspect
phươ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::authorize
phương thức ném một AuthorizationException
nế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 create
cá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ề false
nế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 null
giá 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 before
phương pháp trên chính sách. Các before
phươ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 false
từ before
phương thức này. Nếu null
bị trả lại, kiểm tra ủy quyền sẽ chuyển sang phương thức chính sách.
Các
before
phươ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\User
mô 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: can
và cannot
. Các can
và cannot
phươ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\Post
mô 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, can
phươ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, can
phươ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ư create
vậ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 can
phươ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\User
mô hình, Laravel cung cấp một authorize
phươ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\Controller
lớp cơ sở.
Giống như can
phươ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, authorize
phương thức sẽ ném một Illuminate\Auth\Access\AuthorizationException
ngoạ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ư create
khô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 authorize
phươ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 authorizeResource
phươ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 authorizeResource
phươ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 --model
cờ để 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:policy
lệnh với các--model
tù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\Authorize
phần mềm trung gian được gán can
khóa trong App\Http\Kernel
lớp của bạn . Hãy cùng khám phá một ví dụ về việc sử dụng can
phầ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 can
hai đố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\Post
mô 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ư create
khô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 @can
và @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 @if
và các @unless
câu lệnh. Các câu lệnh @can
và @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 @can
và các @cannot
chỉ 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 $category
tham 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...
}
Giải phóng thời gian, khai phóng năng lực