При разработке веб-проекта, в котором есть учетные записи пользователей, зачастую встает вопрос об организации системы ролей и прав для разграничения доступов к тем или иным разделам и функциям системы. В этой статье мы сравним пакеты для управления доступом и подведем итоги в таблице.

В версии 5.1 Laravel представил Auth Gates — встроенную функцию фреймворка для разграничения доступа. До этого времени приходилось пользоваться различными сторонними пакетами. Однако даже сейчас перед программистом встает выбор: писать все самому или же использовать какой-либо готовый пакет. Первый вариант хорошо подходит для небольших проектов либо проектов с несложной системой прав и ролей. Второй же (при верном выборе пакета) позволяет проводить более тонкую настройку.
Цель данной статьи — обзор существующих пакетов, реализующих RBAC (Role Based Access Control) — управление доступом на основе ролей. Сразу уточним, что на истину в последней инстанции эта статья не претендует: каждый разработчик сам должен определять, какой пакет ему нужен (если он вообще нужен). Примечание: в статье мы рассматриваем именно RBAC, поэтому в обзоре Sentinel затрагиваем только эту часть доступных функций.
Ссылка: https://github.com/spatie/laravel-permission
Документация: https://docs.spatie.be/laravel-permission/v3
Количество загрузок (на момент написания статьи): 3.6М
Версия Laravel: от 5.8 для версии 3
Наличие интерфейса: нет (можно использовать пакет)
Основан на Laravel Auth: да
Особенности
Замечание: при вызове authorize() для policy в случае, если permission имеет такое же имя, как и policy, то сработает оно, а не policy.
Структура БД

Примеры кода
Ссылка: https://github.com/JosephSilber/bouncer
Документация: https://github.com/JosephSilber/bouncer#introduction
Количество загрузок (на момент написания статьи): 418К
Версия Laravel: от 5.1.20
Наличие интерфейса: нет (можно использовать пакет)
Основан на Laravel Auth: да
Особенности
Примечание: создать роль и права для нее можно всего одной строчкой.
Структура БД

Примеры кода
Ограничение права по классу модели или инстансу:
Выдача прав для “своих” сущностей:
Ссылка: https://github.com/santigarcor/laratrust
Документация: https://laratrust.santigarcor.me/
Количество загрузок (на момент написания статьи): 601K
Версия Laravel: ~6.0
Наличие интерфейса: нет
Основан на Laravel Auth: нет
Особенности
Структура БД

Примеры кода
Ссылка: https://github.com/cartalyst/sentinel
Документация: https://cartalyst.com/manual/sentinel/3.x
Количество загрузок (на момент написания статьи): 957K
Версия Laravel: 6.2
Наличие интерфейса: нет
Основан на Laravel Auth: нет
Особенности
Примечание: при установке на чистый Laravel 6.2 и PostgreSQL при миграции появляется ошибка: таблица users уже существует. В этом случае приходится менять стандартную миграцию:

Структура БД

Примеры кода
Ссылка: https://github.com/kodeine/laravel-acl
Документация: https://github.com/kodeine/laravel-acl/wiki
Количество загрузок (на момент написания статьи): 170K
Версия Laravel: 5.0 и выше
Наличие интерфейса: нет
Основан на Laravel Auth: нет
Особенности
Примечание. Некоторые проблемы и решения при миграции:
Структура БД

Примеры кода
Ссылка: https://github.com/mateusjunges/laravel-acl
Документация: https://mateusjunges.github.io/laravel-acl/
Количество загрузок (на момент написания статьи): 1.8K
Версия Laravel: 5.0 и выше
Наличие интерфейса: да (готовые формы)
Основан на Laravel Auth: нет
Особенности
Структура БД


Каждый из перечисленных пакетов имеет свою область применения, поэтому выбрать единственного победителя невозможно. По нашим оценкам, для сложной системы ролей больше всего подходят Laravel-permission и Bouncer, но в то же время есть Laravel-ACL by Kodeine с иерархией ролей. Laravel-ACL by Mateus Junges является “свежим” вариантом и обладает достаточной функциональностью для построения умеренного набора ролей. Sentinel – универсальное решение с кучей фич, помимо управления ролями. Laratrust подойдет тем, кому нравится Entrust.
Также нельзя не упомянуть стандартные средства Laravel – Gates and Policies. Они позволяют легко разграничивать доступ к ресурсам в приложениях, не требующих сложной настройки прав. Если в приложении всего несколько ролей или иерархия не нужна, то ваши потребности можно закрыть с помощью Gates and Policies.
Спасибо за внимание!
Авторские материалы для разработчиков мы также публикуем в наших соцсетях – ВКонтакте и Telegram.

Введение
В версии 5.1 Laravel представил Auth Gates — встроенную функцию фреймворка для разграничения доступа. До этого времени приходилось пользоваться различными сторонними пакетами. Однако даже сейчас перед программистом встает выбор: писать все самому или же использовать какой-либо готовый пакет. Первый вариант хорошо подходит для небольших проектов либо проектов с несложной системой прав и ролей. Второй же (при верном выборе пакета) позволяет проводить более тонкую настройку.
Цель данной статьи — обзор существующих пакетов, реализующих RBAC (Role Based Access Control) — управление доступом на основе ролей. Сразу уточним, что на истину в последней инстанции эта статья не претендует: каждый разработчик сам должен определять, какой пакет ему нужен (если он вообще нужен). Примечание: в статье мы рассматриваем именно RBAC, поэтому в обзоре Sentinel затрагиваем только эту часть доступных функций.
Описание пакетов
Laravel-permission by Spatie
Ссылка: https://github.com/spatie/laravel-permission
Документация: https://docs.spatie.be/laravel-permission/v3
Количество загрузок (на момент написания статьи): 3.6М
Версия Laravel: от 5.8 для версии 3
Наличие интерфейса: нет (можно использовать пакет)
Основан на Laravel Auth: да
Особенности
- Наличие artisan-команд по созданию/присвоению прав.
- Готовые scope по ролям и правам.
- Возможность проверять права пользователя с помощью стандартных средств за счет того, что пакет использует Laravel Auth Gates.
- Возможность использовать blade directives пакета: role (@hasrole), @hasanyrole, @hasallroles, @unlessrole.
- Синхронизация прав и ролей.
Замечание: при вызове authorize() для policy в случае, если permission имеет такое же имя, как и policy, то сработает оно, а не policy.
Структура БД

Примеры кода
// Выдача прав пользователю
$user->givePermissionTo('edit articles');
// Присвоение пользователю ролей
$user->assignRole('writer', 'admin');
// Это можно сделать в виде массива
$user->assignRole(['writer', 'admin']);
// Выдача прав роли
$role->givePermissionTo('edit articles');
Bouncer by Joseph Silber
Ссылка: https://github.com/JosephSilber/bouncer
Документация: https://github.com/JosephSilber/bouncer#introduction
Количество загрузок (на момент написания статьи): 418К
Версия Laravel: от 5.1.20
Наличие интерфейса: нет (можно использовать пакет)
Основан на Laravel Auth: да
Особенности
- Возможность использовать без Laravel.
- Синхронизация прав и ролей.
- Возможность накладывать ограничения на права (по определенному классу модели либо по определенному инстансу.
- Выдача всех прав для “своих” сущностей: с помощью функции “toOwn” можно выдать все права на сущность, которая принадлежит пользователю (сравнение поля user_id и $user->id, можно кастомизировать). Можно ограничить выданные права с помощью функции “to”.
- Поддержка Multitenancy (на основе функции “scope”).
- Возможность с помощью функции “scope” разделять роли и права в зависимости от установленных условий (на основе уникального идентификатора) — например, права в админке и публичной части сайта.
- Консольная artisan команда для очистки БД от неиспользуемых permission.
- Возможность быстро забанить пользователя или снять бан (forbidden ability).
Примечание: создать роль и права для нее можно всего одной строчкой.
Структура БД

Примеры кода
Ограничение права по классу модели или инстансу:
Bouncer::allow($user)->to('edit', Post::class);
Bouncer::allow($user)->to('edit', $post);
Выдача прав для “своих” сущностей:
Bouncer::allow($user)->toOwn(Post::class)->to(['view', 'update']);
Laratrust by Santigarcor
Ссылка: https://github.com/santigarcor/laratrust
Документация: https://laratrust.santigarcor.me/
Количество загрузок (на момент написания статьи): 601K
Версия Laravel: ~6.0
Наличие интерфейса: нет
Основан на Laravel Auth: нет
Особенности
- Это форк ENTRUST (https://github.com/Zizaco/entrust).
- Есть свои blade directives.
- Из-за замены стандартных команд Laravel своими невозможно работать с blade directive can — придется использовать $user->can(‘edit-user’) либо директиву пакета permission.
- Синхронизация ролей/прав.
- Наличие ability — одновременная проверка на роли и права.
- Готовый middleware.
- Multitenancy на основе teams.
Структура БД

Примеры кода
Проверка наличия прав
$user->hasRole(['owner', 'admin']);
$user->can(['edit-user', 'create-post']);
$user->hasRole('owner|admin');
$user->can('edit-user|create-post');
Проверка принадлежности
$user->owns($post) // Проверка по $post->user_id
Создание роли
$owner = new Role();
$owner->name = 'owner';
$owner->display_name = 'Project Owner'; // optional
$owner->description = 'User is the owner of a given project'; // optional
$owner->save();
Sentinel by Cartalyst
Ссылка: https://github.com/cartalyst/sentinel
Документация: https://cartalyst.com/manual/sentinel/3.x
Количество загрузок (на момент написания статьи): 957K
Версия Laravel: 6.2
Наличие интерфейса: нет
Основан на Laravel Auth: нет
Особенности
- Включает в себя не только роли и права, но и все, связанное с регистрацией.
- Пакет является framework agnostic, т.е. его можно использовать не только в Laravel — нужно просто установить следующие зависимости с помощью composer: illuminate/database, illuminate/events, symfony/http-foundation.
- С помощью аддона Sentinel Expired-Permissions можно выдавать права на время.
- Поддерживает Multitenancy с помощью аддона Sentinel Multitenancy.
Примечание: при установке на чистый Laravel 6.2 и PostgreSQL при миграции появляется ошибка: таблица users уже существует. В этом случае приходится менять стандартную миграцию:

Структура БД

Примеры кода
// Присвоение роли
$user = Sentinel::findById(1);
$role = Sentinel::findRoleByName('Subscribers');
$role->users()->attach($user);
// Проверка роли
$admin = Sentinel::inRole('admin');
// Выдача прав
$user->permissions = [
'user.create' => true,
'user.delete' => false,
];
$user->save();
// Проверка прав
$user->hasAccess(['user.create', 'user.update']);
Sentinel::hasAnyAccess(['user.admin', 'user.update']);
Laravel-ACL by Kodeine
Ссылка: https://github.com/kodeine/laravel-acl
Документация: https://github.com/kodeine/laravel-acl/wiki
Количество загрузок (на момент написания статьи): 170K
Версия Laravel: 5.0 и выше
Наличие интерфейса: нет
Основан на Laravel Auth: нет
Особенности
- Синхронизация ролей и прав.
- Наследование прав.
- Наличие своих blade directives: role, permission.
- Наличие готового middleware.
Примечание. Некоторые проблемы и решения при миграции:
- В файле config/acl нужно добавить опцию users_table с именем таблицы пользователей для обеспечения стабильности миграции.
- Нужно установить пакет «doctrine/dbal» на чистом Laravel, чтобы “подружить” его со стандартными миграциями, иначе возможна ошибка при обновлении полей.
Структура БД

Примеры кода
// Наследование прав
$permissionInternship = Permission::create([
'name' => 'internships',
'slug' => [ // массив прав
'create' => true,
'view' => true,
'update' => true,
'delete' => true,
],
'description' => 'manage internships'
]);
$permissionStudent = Permission::create([
'name' => 'internships.student',
'slug' => [ //массив прав только для студента
'create' => false,
],
// само наследование
'inherit_id' => $permissionInternship->getKey(),
'description' => 'student internship permissions'
]);
Laravel-acl by Mateus Junges
Ссылка: https://github.com/mateusjunges/laravel-acl
Документация: https://mateusjunges.github.io/laravel-acl/
Количество загрузок (на момент написания статьи): 1.8K
Версия Laravel: 5.0 и выше
Наличие интерфейса: да (готовые формы)
Основан на Laravel Auth: нет
Особенности
- Готовые scope.
- Синхронизация прав для групп.
- Наличие своих blade directives: group, @elsegroup, permission, @elsepermission, @allpermission,@allgroups, @anypermission, @anygroup
- Наличие встроенных команд для artisan по созданию групп/прав и их отображению, а также отображению прав пользователя.
- Наличие готового middleware: PermissionMiddleware, GroupMiddleware, HierarchicalPermissions, PermissionOrGroupMiddleware.
- Наличие готовых форм для управления ролями.
Структура БД

Сводная таблица

Заключение
Каждый из перечисленных пакетов имеет свою область применения, поэтому выбрать единственного победителя невозможно. По нашим оценкам, для сложной системы ролей больше всего подходят Laravel-permission и Bouncer, но в то же время есть Laravel-ACL by Kodeine с иерархией ролей. Laravel-ACL by Mateus Junges является “свежим” вариантом и обладает достаточной функциональностью для построения умеренного набора ролей. Sentinel – универсальное решение с кучей фич, помимо управления ролями. Laratrust подойдет тем, кому нравится Entrust.
Также нельзя не упомянуть стандартные средства Laravel – Gates and Policies. Они позволяют легко разграничивать доступ к ресурсам в приложениях, не требующих сложной настройки прав. Если в приложении всего несколько ролей или иерархия не нужна, то ваши потребности можно закрыть с помощью Gates and Policies.
Полезные ссылки
- habr.com/ru/post/321678 — для “маленьких” проектов
- laravel-news.com/two-best-roles-permissions-packages — сравнение Bouncer и Laravel-permission
Спасибо за внимание!
Авторские материалы для разработчиков мы также публикуем в наших соцсетях – ВКонтакте и Telegram.