Перейти к содержанию
Innovialabs

RBAC и ABAC: как спроектировать роли и права доступа в приложении

Практика3 мин

Коротко

Начните с RBAC — ролей, которые объединяют именованные права, — и добавляйте ABAC-правила только там, где доступ зависит от данных, например «свои сделки» или «сделки своего филиала», проверяя всё на сервере.

Коротко

  • RBAC (role-based access control): пользователю назначаются роли, роли — права. «Менеджер может редактировать сделки». Просто понять и проверить.
  • ABAC (attribute-based access control): решение принимается по атрибутам пользователя, объекта и контекста. «Менеджер может редактировать сделку, если она из его филиала и не закрыта».

Большинство реальных приложений используют гибрид: RBAC отвечает на вопрос «может ли человек вообще делать такое действие», атрибутные правила — «с какими именно записями».

Сравнение

RBACABAC
На что отвечаетКакие действия разрешает роль?Можно ли это действие с этим объектом сейчас?
Пример в CRMМенеджер продаж видит сделкиМенеджер видит только сделки своего филиала
Сложность настройкиНизкаяВыше: правила нужно продумать и протестировать
АудитПросто: список ролей и правСложнее: нужно читать правила
Типичный рискВзрыв числа ролейПравила, которые никто не понимает

Моделируйте права, а не роли

Самая частая ошибка — проверять роль в коде: if (user.role === "admin"). Когда появляется новая роль, приходится искать все такие проверки. Вместо этого проверяйте права, а роли пусть будут просто их наборами.

CREATE TABLE permissions (
  id   serial PRIMARY KEY,
  code text UNIQUE NOT NULL          -- например 'deals.view', 'deals.edit', 'users.manage'
);
CREATE TABLE roles (
  id   serial PRIMARY KEY,
  name text UNIQUE NOT NULL
);
CREATE TABLE role_permissions (
  role_id       int REFERENCES roles(id),
  permission_id int REFERENCES permissions(id),
  PRIMARY KEY (role_id, permission_id)
);
CREATE TABLE user_roles (
  user_id int REFERENCES users(id),
  role_id int REFERENCES roles(id),
  PRIMARY KEY (user_id, role_id)
);

Коды прав живут в коде как константы, роли — в базе, и их можно менять в админке без релиза.

Атрибуты — там, где важны данные

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

function canEditDeal(user: User, deal: Deal): boolean {
  if (!user.permissions.has("deals.edit")) return false;
  if (deal.status === "closed") return user.permissions.has("deals.edit_closed");
  if (user.permissions.has("deals.edit_any")) return true;
  if (deal.ownerId === user.id) return true;
  return user.permissions.has("deals.edit_branch") && deal.branchId === user.branchId;
}

Для списков применяйте то же правило как фильтр в запросе к базе, а не загружайте всё и прячьте строки в интерфейсе. Иначе API всё равно отдаст данные чужих филиалов, а счётчики пагинации будут неверными.

Проверки — на сервере

  • Интерфейс может скрывать кнопки, но каждый API-эндпоинт сам проверяет права. Запрос можно отправить напрямую, минуя интерфейс.
  • Проверяйте доступ к конкретному объекту, а не только к действию. Замена /deals/42 на /deals/43 не должна открывать чужую сделку — это классическая уязвимость IDOR (broken object level authorization).
  • Запрет по умолчанию: новый эндпоинт без политики должен возвращать 403, а не работать для всех.
  • Логируйте изменения прав и назначение ролей как события безопасности.

Как избежать взрыва ролей

Взрыв ролей начинается, когда каждое исключение превращается в новую роль: «Менеджер Ташкент», «Менеджер Самарканд», «Менеджер Ташкент без экспорта»…

  • Роли описывают должностные функции, а область (филиал, команда, регион) уходит в атрибуты.
  • Разрешите несколько ролей на пользователя вместо комбинированных ролей.
  • Редкие права выдавайте отдельно, а не плодите варианты ролей.
  • Периодически пересматривайте роли: удаляйте неиспользуемые, объединяйте почти одинаковые.
  • Показывайте в админке, что именно разрешает каждая роль, понятным языком.

Пример: админка интернет-магазина

  • Роли: Владелец, Администратор, Контент-менеджер, Поддержка, Склад.
  • Права: products.edit, orders.view, orders.refund, users.manage, settings.payments.
  • Атрибутные правила: поддержка видит заказы, но делает возврат только до лимита из настроек; склад видит только заказы своего склада; никто не может менять собственные роли.

Частые вопросы

Когда доступ не зависит от того, кому принадлежат данные: небольшие внутренние инструменты, простые админки с парой ролей. Как только звучит «только свои» или «только своего филиала», нужны атрибутные правила.

Поможем с этим

Если хотите не разбираться самим, а получить результат — этим мы занимаемся каждый день.

Обсудить проект

Читайте также

Есть идея или задача? Расскажите нам

Ответим в течение рабочего дня и предложим решение. Консультация бесплатная.