Как разделить роли в проекте на Laravel: обзорное сравнение RBAC-пакетов

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




    Введение


    В версии 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: да

    Особенности
    1. Наличие artisan-команд по созданию/присвоению прав.
    2. Готовые scope по ролям и правам.
    3. Возможность проверять права пользователя с помощью стандартных средств за счет того, что пакет использует Laravel Auth Gates.
    4. Возможность использовать blade directives пакета: role (@hasrole), @hasanyrole, @hasallroles, @unlessrole.
    5. Синхронизация прав и ролей.

    Замечание: при вызове 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: да

    Особенности
    1. Возможность использовать без Laravel.
    2. Синхронизация прав и ролей.
    3. Возможность накладывать ограничения на права (по определенному классу модели либо по определенному инстансу.
    4. Выдача всех прав для “своих” сущностей: с помощью функции “toOwn” можно выдать все права на сущность, которая принадлежит пользователю (сравнение поля user_id и $user->id, можно кастомизировать). Можно ограничить выданные права с помощью функции “to”.
    5. Поддержка Multitenancy (на основе функции “scope”).
    6. Возможность с помощью функции “scope” разделять роли и права в зависимости от установленных условий (на основе уникального идентификатора) — например, права в админке и публичной части сайта.
    7. Консольная artisan команда для очистки БД от неиспользуемых permission.
    8. Возможность быстро забанить пользователя или снять бан (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: нет

    Особенности
    1. Это форк ENTRUST (https://github.com/Zizaco/entrust).
    2. Есть свои blade directives.
    3. Из-за замены стандартных команд Laravel своими невозможно работать с blade directive can — придется использовать $user->can(‘edit-user’) либо директиву пакета permission.
    4. Синхронизация ролей/прав.
    5. Наличие ability — одновременная проверка на роли и права.
    6. Готовый middleware.
    7. 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: нет

    Особенности
    1. Включает в себя не только роли и права, но и все, связанное с регистрацией.
    2. Пакет является framework agnostic, т.е. его можно использовать не только в Laravel — нужно просто установить следующие зависимости с помощью composer: illuminate/database, illuminate/events, symfony/http-foundation.
    3. С помощью аддона Sentinel Expired-Permissions можно выдавать права на время.
    4. Поддерживает 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: нет

    Особенности
    1. Синхронизация ролей и прав.
    2. Наследование прав.
    3. Наличие своих blade directives: role, permission.
    4. Наличие готового 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: нет

    Особенности
    1. Готовые scope.
    2. Синхронизация прав для групп.
    3. Наличие своих blade directives: group, @elsegroup, permission, @elsepermission, @allpermission,@allgroups, @anypermission, @anygroup
    4. Наличие встроенных команд для artisan по созданию групп/прав и их отображению, а также отображению прав пользователя.
    5. Наличие готового middleware: PermissionMiddleware, GroupMiddleware, HierarchicalPermissions, PermissionOrGroupMiddleware.
    6. Наличие готовых форм для управления ролями.

    Структура БД



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





    Заключение


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

    Также нельзя не упомянуть стандартные средства Laravel – Gates and Policies. Они позволяют легко разграничивать доступ к ресурсам в приложениях, не требующих сложной настройки прав. Если в приложении всего несколько ролей или иерархия не нужна, то ваши потребности можно закрыть с помощью Gates and Policies.

    Полезные ссылки


    SimbirSoft
    Лидер в разработке современных ИТ-решений на заказ

    Комментарии 2

      0
      Годнота! Спасибо!
        0

        Многие перепробовал, больше всего нравится bouncer, но, похоже, он умирает. Автор на pr не реагирует достаточно продолжительное время, а там есть важные фиксы.

        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

        Самое читаемое