2 Package tốt nhất để phân quyền trong Laravel

2 Package tốt nhất để phân quyền trong Laravel

Chắc hẳn bạn cũng biết vai trò và quyền là một phần quan trọng trong các ứng dụng web. Từ trước tới nay đã có rất nhiều package hỗ trợ việc phân quyền nhưng có 2 gói tới thời điểm hiện tại vẫn được xem là tốt nhất.

Tại sao cần sử dụng Package?

Bản thân sử dụng Laravel cũng có thể viết code logic để phân quyền mà không cần phải sử dụng package. Ta có những thứ như sau:

  • Gates and Policies
  • $this->authorize() method
  • @can and @cannot Blade commands

Có thể nói rằng chỉ Laravel là đủ và không cần package. Nhưng chúng ta vẫn cần các package để việc quản lý các quyền và vai trò dễ dàng hơn so với sử dụng phân quyền bằng Laravel thuần. Có hai gói làm điều đó thực sự tốt và được cập nhật liên tục:

Có một số package khác, nhưng nó có vẻ đã lỗi thời và không còn hoạt động. Tuy nhiên, bạn có thể muốn xem qua chúng:

Bây giờ, chúng ta hãy đi sâu hơn để đánh giá 2 package được lựa chọn và khuyên dùng

Thực tế những gói này làm được gì?

Chúng cung cấp cho bạn một API để giải quyết các vai trò và quyền dễ dàng hơn. Thân thiện với người đọc và dễ hiểu hơn.

Thay vì tạo tất cả các quy tắc trong Policies and Gates , vốn sẽ bị phân mảnh ở một vài nơi khác nhau, bạn sẽ có code như sau:

$user->givePermissionTo('edit articles'); // Spatie package
$user->allow('ban-users'); // Bouncer package

Về cơ bản, hai gói cung cấp chức năng tương tự nhau, nhưng với cấu trúc cơ sở dữ liệu và cú pháp hơi khác nhau một chút.

Cài đặt và sử dụng

Cả hai gói đều được cài đặt tương tự:

  • Thêm vào composer và cài đặt.
  • Các bước cài đặt bạn có thể xem chi tiết trên github hoặc document của package

Cả hai gói đều có tài liệu rõ ràng nên rất dễ cài đặt và sử dụng.

Cấu trúc cơ sở dữ liệu

Cơ sở dữ liệu của Spatie:

Giải thích:

  • Trường guard_name có giá trị mặc định là gói web và cho phép sử dụng nhiều guard .
  • Như bạn có thể thấy, có hai bảng pivot cho các quyền — một bảng có vai trò và một bảng người dùng tương ứng.
  • Trường model_type có giá trị mặc định là App\User nên không có khóa ngoại trực tiếp cho bảng người dùng, không có bảng nào khác có trường user_id  mà sẽ thay bằng model_id để liên kết với bảng người dùng sử dụng quyền.

Cơ sở dữ liệu của Bouncer:

Khá là khác biệt. Và thậm chí ít mối quan hệ hơn.

  • Cái mà Spatie gọi là “permissions, Bouncer gọi là “abilities” Và sau đó, bảng “permissions” là một tập hợp các khả năng được gắn với một “entity”.
  • entity” (trong tất cả các bảng) là một đối tượng để gán các abilities. Nó có thể là một vai trò hoặc một người dùng. Do đó, không có mối quan hệ trực tiếp đến user_id hoặc bảng User ; giống như với package của Spatie.
  • Có một vài trường khác nhau từ các gói: abilities.title, abilities.only_owned,roles.level. Chúng thêm một số chức năng bổ sung, nhưng nó không được giải thích rõ trong tệp README.
  • Spatie có các trường guard còn trong Bouncer không có.

Nhìn chung, cấu trúc cơ sở dữ liệu của Bouncer có vẻ phức tạp hơn một chút và khó hiểu hơn lúc đầu, nhưng đi kèm với đó là sự linh hoạt hơn một chút.

Các method có sẵn

Các package này cung cấp chức năng tương tự nhau, vì vậy hãy so sánh chi tiết.

Tạo Roles/Permissions/Abilities

Spatie

Bạn có thể sử dụng Facade của package như các Facade bình thường của Laravel:

use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
Role::create(['name' => 'writer']);
Permission::create(['name' => 'edit articles']);

Bouncer

Bạn có thể tạo ra role và ability cũng như chỉ định tất cả trong một dòng code:

Bouncer::allow('admin')->to('ban-users');

Chỉ vậy thôi nhưng đằng sau nó Bouncer sẽ tạo 1 Role model và Ability model

Nhưng bạn cũng có thể tạo với Facade như sau:

use Silber\Bouncer\Database\Ability;
Ability::create(['name' => 'edit articles']);

Bouncer có nhiều chức năng hơn ở đây với tính năng tạo model tự động.

Chỉ định vai trò cho người dùng

Spatie

$user->assignRole('writer');
$user->assignRole(['writer', 'admin']);
$user->removeRole('writer');

Các vai trò cũng có thể được đồng bộ hóa:

// Tất cả các role hiện được gán sẽ bị xóa và thay bằng role mới
$user->syncRoles(['writer', 'admin']);

Bouncer

$user->assign('admin');
$user->assign(['writer', 'admin']);
$user->retract('admin');

Cả hai package đều chấp nhận các tham số vai trò là mảng hoặc 1 chuỗi role đơn lẻ.

Nhưng package của Spatie có lợi thế hơn khi có method syncRoles. Nó rất tiện dụng; với Bouncer bạn cần thực hiện thủ công với một vài thao tác.

Chỉ định Quyền / Khả năng cho Người dùng

Spatie

$user->givePermissionTo('edit articles');
$user->givePermissionTo('edit articles', 'delete articles');
$user->revokePermissionTo('edit articles');

Bouncer

$user->allow('ban-users');
$user->allow(['ban-users', 'edit-articles']);

Bạn có thể truyền tên model làm đối số thứ hai.

Bouncer::allow($user)->to('edit', Post::class);
Bouncer::allow($user)->to('edit', $post);
$user->disallow('ban-users');
Bouncer::disallow($user)->to('delete', Post::class);

Chức năng tương tự, nhưng Bouncer cung cấp khả năng truyền qua 1 model hoặc 1 instance.

Kiểm tra Permissions/Roles của người dùng

Spatie

Kiểm tra vai trò

$user->hasRole('writer');
$user->hasAnyRole(Role::all());
$user->hasAllRoles(Role::all());

Kiểm tra quyền

$user->can('edit articles');
$role->hasPermissionTo('edit articles');

Bouncer

Kiểm tra vai trò

$user->isAn('admin');
$user->isA('subscriber', 'editor');
$user->isAll('editor', 'moderator');
$user->isNot('subscriber', 'moderator');

Kiểm tra quyền

Bouncer::allows('edit articles')

Phần này khá giống nhau trong cả hai package.

Blade

Spatie

@role('writer')
    I'm a writer!
@else
    I'm not a writer...
@endrole

@hasanyrole('writer|admin')
    I have one or more of these roles!
@else
    I have none of these roles...
@endhasanyrole

Bouncer

Bouncer không thêm các chỉ thị Blade của riêng mình.

Package Spatie sẽ có nhiều chức năng hơn. Tất nhiên, với cả hai package, bạn đều có thể sử dụng các lệnh Laravel mặc định như @can@endcan .

Caching

Spatie

Dữ liệu vai trò và quyền được tự động lưu vào bộ nhớ đệm để tăng tốc hiệu suất.

Để đặt lại bộ đệm ẩn cho gói này theo cách thủ công dùng lệnh sau:

php artisan cache:forget spatie.permission.cache

Bouncer

Tất cả các truy vấn được thực thi bởi bouncer được lưu vào bộ nhớ đệm cho yêu cầu hiện tại. Nếu bạn bật bộ nhớ đệm theo yêu cầu chéo, bộ nhớ đệm sẽ vẫn tồn tại trên các yêu cầu khác nhau.

Bất cứ khi nào bạn cần, bạn có thể làm mới toàn bộ bộ nhớ cache:

Bouncer::refresh();

Ngoài ra, bạn có thể làm mới bộ nhớ cache chỉ cho một người dùng cụ thể:

Bouncer::refreshFor($user);

Kết luận chung

Cả hai package đều thực sự tốt, và mỗi package có 1 lợi thế riêng.

Ưu điểm của Spatie:

  • Document tốt hơn một chút (một số method của Bouncer không được đề cập trong README)
  • Cấu trúc DB dễ hiểu hơn
  • Method syncRoles() hữu ích hơn thay vì cách thêm và xóa
  • Một vài lệnh blade - @role và @hasanyrole
  • Khả năng sử dụng nhiều guard

Ưu điểm của Bouncer:

  • Tạo role/ability và chỉ định nó — tất cả trong một câu
  • Cho phép hoặc không cho phép quyền dựa trên model hoặc instance của nó
  • Cơ chế bộ nhớ đệm tốt hơn một chút
  • Cấu trúc DB mạnh mẽ hơn một chút với một vài trường hữu ích hơn

Cá nhân mình thì thích và hay sử dụng Laravel permission của Spatie.

Cảm ơn các bạn đã theo dõi bài viết của mình!