Hướng dẫn xây dựng “Simple ACL” Trong Laravel
Việc xác thực của Laravel (authentication) cung cấp 1 giải pháp đơn giản hóa cho việc đăng ký, đăng nhập, đăng xuất, và reset mật khẩu cũng như triển khai nó một cách nhanh chóng và dễ dàng hơn cho ứng dụng web.
Tuy nhiên nếu bạn cần kiểm soát quyền truy cập vào một số phần của trang web, hoặc bật tắt từng phần cụ thể của một trang cho người không phải quản trị viên, hoặc đảm bảo một người nào đó chỉ có thể chỉnh sửa danh bạ của riêng mình, bạn cần xây dựng ACL: Access Control Lists trên laravel (từ version Laravel 5.1.11 trở đi).
Để xây dựng 1 ACL cho ứng dụng chúng ta dùng Class Gate đã được xây dựng sẵn và tích hợp vào các phiên bản laravel từ 5.1.11 trở đi. Class Gate cho phép bạn kiểm tra một user (hoặc người sử dụng đang đăng nhập hoặc một người dùng cụ thể nào đó) là “được phép” để làm một điều gì đó. Chúng ta cùng xem code mẫu bên dưới:
if (Gate::denies(‘update-contact’, $contact)) {
abort(403);
}
Bỏ code trên vào controller của bạn và kiểm tra user đang đăng nhập có bị từ chối quyền update-contact hay không, chúng ta có thể dùng Gate::allows để làm việc ngược lại.
ACL của laravel xây dựng dựa trên khái kiệm “Ability“. 1 Ability là 1 key (vd update-contact).
ĐỊNH NGHĨA 1 Ability CHO ACL
Định nghĩa 1 “Ability” trong vị trí 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;
});
}}
Và kiểm tra
if (Gate::denies('update-contact', $contact)) {
abort(403);
}
1 khái niệm khác chúng ta nên tham khảo là Policies, thay vì phải viết trực tiếp quá nhiều các định nghĩa vào AuthServiceProvider, chúng ta có thể xây dựng tập hợp nhiều class Policies.
Chạy command line
php artisan make:policy ContactPolicy
sẽ tự động tạo file ContactPolicy vào folder app/Policies với nội dung được tạo tự động.
<?php
namespace App\Policies;
class ContactPolicy
{
/**
* Create a new policy instance.
*
* @return void
*/
public function __construct()
{
//
}
//viết thêm phương thức update
public function update($user, $contact)
{
return $user->id === $contact->user_id;
}
}
Chúng ta đăng ký class vào AuthServiceProvider
class AuthServiceProvider extends ServiceProvider
{
protected $policies = [
Contact::class => ContactPolicy::class,
];
và bây giờ chúng ta có thể đặt vào controller để kiểm tra
if (Gate::denies('update', $contact)) {
abort(403);
}