ACL (Access Control List) Authorization in Laravel 5.1
Bài đăng này đã không được cập nhật trong 3 năm
1. Giới thiệu về ACL trong Laravel 5.1
Authorization được đưa vào laravel từ phiên bản 5.1.11. Từ phiên bản này, ALC của laravel được gọi là Gate
. Bằng việc sử dụng Gate
, chúng ta có thể dễ dàng kiểm tra nếu 1 user
(đã login hay 1 user
đặc biệt nào đó) có "được phép" - allow thực thi một hành động nào đó hay không một cách đơn giản.
if (Gate::denies('update-contact', $contact)) {
abort(403);
}
2. Cách thức hoạt động của ACL
- Defining Abilities
Hãy bắt đầu bằng cách định nghĩa một ability (khả năng) trong provider mặc định AuthServiceProvider
:
...
class AuthServiceProvider extends ServiceProvider
{
public function boot(GateContract $gate) {
parent::registerPolicies($gate);
$gate->define('update-contact', function ($user, $contact) {
return $user->id === $contact->user_id;
});
}
}
Như chúng ta thấy, tham số đầu tiên được đưa vào là user
. Nếu chưa có user
nào login thì Gate
luôn trả về giá trị false
cho tất cả các trường hợp. Ngoài cách trên, chúng ta có thể truyển vào class
name và method tương ứng vào tương tự như khi khai báo route trong laravel.
$gate->define('update-post', 'PostACLCheckerThingie@update');
- Checking with Façades
Gate
cho phép chúng ta kiểm tra bằng cách hàm: check
, allows
hay denies
(check
tương tự như allows
, trả về cùng 1 kết quả, còn denies
thì ngược lại). Nếu chúng ta sử dụng façade, chúng ta không cần phải truyền vào tham số user
, façade
sẽ tự động truyền user
đang login như tham số user
:
if (Gate::denies('update-contact', $contact)) {
abort(403);
}
if (Gate::allows('create-contact')) {
redirect('hooray');
}
Nếu chúng ta sử dụng Ability với nhiều tham số:
$gate->define('delete-interaction', function ($user, $contact, $interaction) {
// Do stuff...
});
if (Gate::allows('delete-interaction', [$contact, $interaction]) {
// Do stuff...
});
Nếu chúng ta muốn kiểm tra "quyền" của 1 user
đặc biệt nào đó thì có thể sử dụng Gate::forUser($user)
thay thế cho Gate
ở các ví dụ trên
- Checking on the user model
Từ phiên bản 5.1.* trở đi, model Laravel's App\User cung cấp thêm 2 hàm can
và cannot
, tương ứng với allows
và denies
trong Gate
. Để sử dụng được chúng ta phải khai báo model đó Authorizable
. Sau đó chúng ta có thể sử dụng can
và cannot
ở bất cứ đâu, trong controller
, view
,...
if ($user->can('update-contact', $contact)) {
// Do stuff
}
- Checking in Blade
Bằng việc khai báo model Authorizable
, chúng ta có thể sử dụng gate
ngay trong blade
<nav>
<a href="/">Home</a>
@can('edit-contact', $contact)
<a href="{{ route('contacts.edit', [$contact->id]) }}">Edit This Contact</a>
@endcan
</nav>
- Intercepting checks
Trong một số trường hợp chúng ta có thể chặn việc kiểm tra trong gate
bằng hàm before
, hàm này sẽ trả về giá trị trước tất cả các bước check
$gate->before(function ($user, $ability) {
if ($user->isOwner()) {
return true;
}
});
- Policies
Ngoài cách viết các abilities vào trong provider mặc định là AuthServiceProvider
, chúng ta có thể viết các abilities vào các Policy
tương ứng để dễ quản lý hơn.
php artisan make:policy ContactPolicy
Sau khi tạo thành công Policy
, chúng ta khai báo nó trong: AuthServiceProvider
class AuthServiceProvider extends ServiceProvider
{
protected $policies = [
Contact::class => ContactPolicy::class,
];
Để tạo ability update
cho model Contact
, chúng ta viết nó vào ContractPolicy
vừa tạo ở trên.
<?php
namespace App\Policies;
class ContactPolicy
{
public function update($user, $contact) {
return $user->id === $contact->user_id;
}
}
- Controller authorization
Ngoài các cách kiểm tra authorize thông thường, chúng ta có thể sử dụng gate
ngay trong controller. Gate
sẽ throw exception 403 nếu authorization fails.
public function update($id)
{
$contact = Contact::findOrFail($id);
$this->authorize('update', $contact);
// Do stuff...
}
3. Kết luận
Với việc kết hợp gate
một cách hợp lý, việc xử lý các câu lệnh phức tạp sẽ ngắn gọn hơn rất nhiều, đồng thời thể hiện rõ hơn hành động trong cách đặt tên cho mỗi ability
, code của chúng ta sẽ sáng sủa và dễ hiểu hơn rất nhiều.
- Bài viết có tham khảo: https://mattstauffer.co/blog/acl-access-control-list-authorization-in-laravel-5-1
All rights reserved