Реалізація RBAC (Role-Based Access Control) для веб-застосунку

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.
Розробка та обслуговування будь-яких видів сайтів:
Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Реалізація RBAC (Role-Based Access Control) для веб-застосунку
Середня
~3-5 робочих днів
Часті питання
Наші компетенції:
Етапи розробки
Останні роботи
  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Впровадження RBAC (Role-Based Access Control) для веб-додатків

Користувач входить у систему і бачить рівно те, що він авторизований бачити — не більше і не менше. Звучить тривіально, поки ви не починаєте рахувати: 12 типів користувачів, 40 розділів інтерфейсу, матриця дозволів на аркуші A3, яку потрібно підтримувати в коді. RBAC — стандартна відповідь: права призначаються не користувачам напрямо, а ролям, а користувачі отримують ролі.

Модель даних

Мінімальна схема для PostgreSQL:

CREATE TABLE roles (
    id          SERIAL PRIMARY KEY,
    name        VARCHAR(64) NOT NULL UNIQUE,  -- 'admin', 'editor', 'viewer'
    description TEXT
);

CREATE TABLE permissions (
    id       SERIAL PRIMARY KEY,
    resource VARCHAR(128) NOT NULL,  -- 'articles', 'users', 'reports'
    action   VARCHAR(64)  NOT NULL,  -- 'create', 'read', 'update', 'delete', 'publish'
    UNIQUE (resource, action)
);

CREATE TABLE role_permissions (
    role_id       INT REFERENCES roles(id)       ON DELETE CASCADE,
    permission_id INT REFERENCES permissions(id) ON DELETE CASCADE,
    PRIMARY KEY (role_id, permission_id)
);

CREATE TABLE user_roles (
    user_id INT REFERENCES users(id) ON DELETE CASCADE,
    role_id INT REFERENCES roles(id) ON DELETE CASCADE,
    PRIMARY KEY (user_id, role_id)
);

Це класична реалізація RBAC0. Для ієрархічних ролей (admin наслідує всі права editor), додайте таблицю role_hierarchy з полями parent_role_id / child_role_id та використовуйте рекурсивний CTE при перевірці.

Перевірка дозволів на бекенді

Node.js + Express, middleware-підхід:

// permissions.js — завантажуємо дозволи з бази при старті або кешуємо в Redis
async function loadUserPermissions(userId) {
  const rows = await db.query(`
    SELECT DISTINCT p.resource, p.action
    FROM user_roles ur
    JOIN role_permissions rp ON rp.role_id = ur.role_id
    JOIN permissions p ON p.id = rp.permission_id
    WHERE ur.user_id = $1
  `, [userId]);

  return new Set(rows.map(r => `${r.resource}:${r.action}`));
}

// middleware/can.js
function can(resource, action) {
  return async (req, res, next) => {
    const perms = await loadUserPermissions(req.user.id);
    if (perms.has(`${resource}:${action}`)) {
      return next();
    }
    res.status(403).json({ error: 'Forbidden' });
  };
}

// routes
router.delete('/articles/:id', authenticate, can('articles', 'delete'), deleteArticle);
router.post('/articles',       authenticate, can('articles', 'create'), createArticle);

Для PHP/Laravel паттерн аналогічний — Gate та Policy:

// AuthServiceProvider
Gate::before(function (User $user, string $ability) {
    if ($user->hasRole('superadmin')) {
        return true; // superadmin обходить всі перевірки
    }
});

Gate::define('articles.delete', function (User $user) {
    return $user->hasPermission('articles', 'delete');
});

// У контролері
public function destroy(Article $article)
{
    $this->authorize('articles.delete');
    $article->delete();
    return response()->noContent();
}

Метод hasPermission робить один запит із JOIN або бере з кешу — залежить від навантаження.

Кеширування матриці дозволів

Гоняти JOIN через три таблиці на кожен HTTP-запит — витратно. Дозволи користувача змінюються рідко — це добре кешується:

// redis cache, TTL 5 хвилин
async function getUserPermissions(userId) {
  const cacheKey = `user_perms:${userId}`;
  const cached = await redis.get(cacheKey);
  if (cached) return new Set(JSON.parse(cached));

  const perms = await loadUserPermissions(userId);
  await redis.setex(cacheKey, 300, JSON.stringify([...perms]));
  return perms;
}

// Інвалідація при зміні ролей користувача
async function assignRole(userId, roleId) {
  await db.query(
    'INSERT INTO user_roles (user_id, role_id) VALUES ($1, $2) ON CONFLICT DO NOTHING',
    [userId, roleId]
  );
  await redis.del(`user_perms:${userId}`);
}

Управління ролями в інтерфейсі

Адміністратор повинен бачити й редагувати матрицю. Мінімальний API:

GET    /api/roles                    — список ролей
POST   /api/roles                    — створити роль
GET    /api/roles/:id/permissions    — дозволи ролі
PUT    /api/roles/:id/permissions    — оновити дозволи ролі (масив permission_ids)
GET    /api/users/:id/roles          — ролі користувача
POST   /api/users/:id/roles          — призначити роль
DELETE /api/users/:id/roles/:roleId  — зняти роль

На фронті таблиця з чекбоксами resource × action — стандартний UI для такого екрану.

Що впливає на терміни

Базова реалізація (3–5 ролей, без наслідування, без UI управління ролями) — 2–3 дні. Це схема, middleware, інтеграція з існуючою аутентифікацією, тести.

Якщо додається UI для управління ролями та дозволами — ще 2 дні. Якщо ієрархічні ролі або мультитенантність (ролі ізольовані по організації) — додаємо ще 2–3 дні на ускладнення схеми та логіки перевірок.