Как должна выглядеть реализация гибкой системы управления доступом?
Приветствую. У меня есть свое API, и я хочу реализовать достаточно гибкое управление доступом к методам. У меня есть различные типы пользователей (администратор, модератор,...), которые могут динамически создаваться и удаляться, можно редактировать уровень разрешений, который доступен каждому типу пользователя. У каждого типа пользователя есть свой приоритет.
Вот некоторые абстрактные примеры, которые я хочу, чтобы поддерживала система управления доступом:
- модератор может банить пользователей, которые ниже его по приоритету.
- пользователь может редактировать свои сообщения, модератор может редактировать как свои, так и чужие сообщения.
- модератор может удалять сообщения не во всех беседах, а только в заранее выбранных администратором.
Я рассматривал модель управления доступом на основе ролей (RBAC), но она дает мне возможность лишь определять, может ли тип пользователя Х вызывать метод Y. Но этого недостаточно: все могут вызывать метод messages.edit, но все с разными правами — пользователям доступно редактирование своих сообщений, модераторам — любых сообщений. Возможно, можно как-то модифицировать RBAC, чтобы она поддерживала такие вещи?
Читал про управление доступом на основе атрибутов (ABAC), в том числе и на хабре, но, в отличии от RBAC (где вся реализация — это таблицы permissions, roles, roles_permissions, users и users_roles), не совсем понятно, как это реализовать на практике и будет ли это удобно в использовании.
Буду благодарен вам за ваши идеи и рекомендации. Меня интересует именно сама концепция того, как это можно сделать..
Зависит от того, как вы хотите этим пользоваться. Если некто должен иметь возможность натыкать разрешений-галочек в админке, то это точно RBAC. Если не нужна такая возможность, то ACL/ABAC.
RBAC можно комбинировать, т.е. не просто проверить наличие разрешения, а вызвать некий код, который проверит это разрешение в каком-то контексте. Например, по аналогии с политиками в Laravel.
Большое спасибо за ответ!
Да, этот некто должен иметь возможность насоздавать типов пользователей (администраторов, техподдержку, модераторов, ...), а потом "натыкать" галочек-разрешений для каждого из них, в этом главная задумка. Значит для такого случая RBAC подходит лучше всего?
Для случаев вида "модератор может редактировать как свои, так и чужие сообщения" разумно просто создать несколько разрешений: messages.edit:basic (разрешение на редактирование своих сообщений), messages.edit:all (редактирование любых сообщений) ?
Но как быть в этом случае: "модератор может удалять сообщения не во всех беседах, а только в заранее выбранных администратором"? Тут уже не пойдет создать несколько разрешений... Да, у меня будет нечто похожее на политики в Laravel - если я правильно понимаю, это классы, в которых куча булевых методов, определяющих, можно ли выполнить действие Y. В этих методах я и должен проверять, например, то, что модератор хочет удалить сообщение в чате из разрешенного списка? Тогда у меня будет разрешение messages.delete:all_in_allowed_chats(право удалять любые сообщения в разрешенных чатах) и будет где-то хранится список разрешенных чатов для этого пользователя.
TAnonim, мне видится просто разрешение messages.delete, а в политике можно проверять, кто хочет удалить сообщение и в каком чате, с любыми дополнительными проверками. Чем мельче дробите разрешения, тем сложнее потом будет, рано или поздно они начнут конфликтовать.
JhaoDa, Да, я тоже не хотел дробить разрешения... Хорошо, вот в методе политики я узнал, что пользователь может в принципе вызывать messages.delete. Откуда политике узнать "подробности разрешения" - что пользователь может удалять любые сообщения в определенных чатах, если это не указано в самом разрешении?
TAnonim, ну так политика и будет иметь логику для того, чтобы это узнать. Из БД вычитать, из конфига, к какому-то сервису обратиться, фазу Луны проверить — что угодно, я же и написал «с любыми дополнительными проверками». Вы открывали ссылку, что я вам дал?
JhaoDa, Благодарю за ответ.
Разумеется, открывал и читал. Понятно, что методы политики могут проверять что угодно и содержать любую логику.
Допустим у меня будет дополнительная таблица permissions_data, которая будет содержать подробности каждого разрешения для каждой роли. Вопрос в том, чем это лучше кучи мелких разрешений, какие могут быть конфликты у мелких разрешений?
TAnonim, откуда ж мне знать, какие у вас могут быть конфликты? Но чуйка и опыт подсказывают, что рано или поздно несколько мелких разрешений на удаление сообщений начнут конфликтовать, или их придётся дробить ещё мельче, или ещё что-то...
JhaoDa, простите, что надоедаю, но хочу задать последний вопрос.
Не могли бы вы привести пример конфликта мелких разрешений, чтобы я понимал, чего опасаться?
И, главное: почему же все таки лучше хранить информацию о подробностях разрешений отдельно, чем делать мелкие — я не вижу отличий между этими подходами... Т. е. почему конфликтов не будет в случае хранения информации о подробностях отдельно?
TAnonim, ну я же говорю — откуда мне знать? Я не утверждаю, что они будут, но мне кажется, что они возможны.
Я не могу обосновать своё видение решения вашей задачи с железобетонными пруфами, я вообще не люблю RBAC.