Реализация ABAC (Attribute-Based Access Control) для веб-приложения

Мы часто сталкиваемся с ситуацией, когда RBAC трещит по швам. В одном проекте после внедрения RBAC мы получили 47 запросов на изменение ролей за месяц — каждое требовало согласования. ABAC сократил это до 2 запросов. Появляются правила вроде «пользователь может редактировать документ, если он его ав

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
Реализация ABAC (Attribute-Based Access Control) для веб-приложения
Сложный
~5 дней

Наши компетенции:

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1414
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1285
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    982
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1241
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    982
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Разработка веб-сайта для компании ФИКСПЕР
    994

Мы часто сталкиваемся с ситуацией, когда RBAC трещит по швам. В одном проекте после внедрения RBAC мы получили 47 запросов на изменение ролей за месяц — каждое требовало согласования. ABAC сократил это до 2 запросов. Появляются правила вроде «пользователь может редактировать документ, если он его автор, документ находится в статусе draft, и пользователь работает в той же организации, что и документ». Роль тут не поможет — нужен контекст. ABAC (Attribute-Based Access Control) принимает решение на основе атрибутов субъекта (пользователя), объекта (ресурса) и среды (время, IP, контекст запроса). Наш опыт показывает, что гибрид RBAC+ABAC даёт оптимальный баланс производительности и гибкости. Мы гарантируем прозрачность решений с помощью детального аудита.

Как устроена модель

Четыре сущности в ABAC:

  • Subject — пользователь и его атрибуты: role, department, clearance_level, org_id.
  • Resource — объект и его атрибуты: owner_id, status, org_id, classification, region.
  • Action — read, write, delete, approve.
  • Environment — time_of_day, ip_address, request_method.

Политика — это предикат над этими атрибутами. Например:

ALLOW IF subject.org_id == resource.org_id AND (subject.role == 'editor' OR subject.id == resource.owner_id) AND resource.status IN ('draft', 'review') AND action == 'write' 

Почему ABAC лучше RBAC?

RBAC прост и быстр, но не масштабируется для сложных правил. ABAC позволяет выразить практически любое бизнес-ограничение: «менеджер может одобрить заявку, если сумма < 10000 и заявка создана в его отделе». В RBAC пришлось бы вводить новую роль. ABAC решает это декларативно. Сравним ключевые параметры:

Критерий RBAC ABAC
Гибкость Низкая (роли фиксированы) Высокая (атрибуты)
Поддержка контекста Нет Да
Производительность Высокая Средняя (при большом числе политик)
Сложность внедрения Низкая Средняя

Схема хранения политик

Можно хранить политики в коде (подходит для небольшого числа правил) или в базе с DSL. Вот вариант с хранением в PostgreSQL в виде JSON-условий:

CREATE TABLE abac_policies ( id SERIAL PRIMARY KEY, name VARCHAR(128) NOT NULL, description TEXT, effect VARCHAR(8) NOT NULL CHECK (effect IN ('allow', 'deny')), priority INT NOT NULL DEFAULT 0, conditions JSONB NOT NULL, -- дерево условий actions TEXT[] NOT NULL, resources TEXT[] NOT NULL -- glob: 'documents', 'documents/*' ); -- Пример записи INSERT INTO abac_policies (name, effect, priority, conditions, actions, resources) VALUES ( 'editors_can_write_own_draft', 'allow', 10, '{ "operator": "AND", "conditions": [ {"attribute": "subject.role", "op": "in", "value": ["editor", "senior_editor"]}, {"attribute": "subject.org_id", "op": "eq", "value": {"ref": "resource.org_id"}}, {"attribute": "resource.status", "op": "in", "value": ["draft", "review"]} ] }', ARRAY['write', 'delete'], ARRAY['documents', 'documents/*'] ); 

Движок принятия решений

class ABACEngine { constructor(policies) { // Политики предзагружены и отсортированы по приоритету (deny > allow при конфликте) this.policies = policies.sort((a, b) => { if (a.effect === 'deny' && b.effect !== 'deny') return -1; return b.priority - a.priority; }); } evaluate(subject, resource, action, environment = {}) { const context = { subject, resource, action, environment }; for (const policy of this.policies) { if (!policy.actions.includes(action)) continue; if (!this.matchesResource(policy.resources, resource.type)) continue; if (this.evaluateCondition(policy.conditions, context)) { return policy.effect === 'allow'; } } return false; // default deny } evaluateCondition(condition, ctx) { if (condition.operator === 'AND') { return condition.conditions.every(c => this.evaluateCondition(c, ctx)); } if (condition.operator === 'OR') { return condition.conditions.some(c => this.evaluateCondition(c, ctx)); } if (condition.operator === 'NOT') { return !this.evaluateCondition(condition.condition, ctx); } // Листовой узел const leftVal = this.resolveAttribute(condition.attribute, ctx); const rightVal = condition.value?.ref ? this.resolveAttribute(condition.value.ref, ctx) : condition.value; switch (condition.op) { case 'eq': return leftVal === rightVal; case 'neq': return leftVal !== rightVal; case 'in': return Array.isArray(rightVal) && rightVal.includes(leftVal); case 'gte': return leftVal >= rightVal; case 'lte': return leftVal <= rightVal; case 'contains': return Array.isArray(leftVal) && leftVal.includes(rightVal); default: return false; } } resolveAttribute(path, ctx) { // 'subject.org_id' → ctx.subject.org_id return path.split('.').reduce((obj, key) => obj?.[key], ctx); } matchesResource(patterns, resourceType) { return patterns.some(p => p === resourceType || (p.endsWith('/*') && resourceType.startsWith(p.slice(0, -2))) ); } } 

Как интегрировать ABAC в Express?

const engine = new ABACEngine(await loadPoliciesFromDB()); // Перезагрузка политик при изменении (без рестарта сервера) db.on('policy_changed', async () => { engine.updatePolicies(await loadPoliciesFromDB()); }); function abac(action) { return async (req, res, next) => { const resource = await loadResource(req); // загружаем объект со всеми атрибутами const allowed = engine.evaluate( req.user, // subject resource, // resource action, // action { // environment ip: req.ip, timestamp: Date.now(), userAgent: req.headers['user-agent'], } ); if (!allowed) { return res.status(403).json({ error: 'Forbidden' }); } req.resource = resource; next(); }; } router.put('/documents/:id', authenticate, abac('write'), updateDocument); router.delete('/documents/:id', authenticate, abac('delete'), deleteDocument); 

Audit log

ABAC без аудита — слепой инструмент. Каждое решение движка логируется:

CREATE TABLE abac_audit_log ( id BIGSERIAL PRIMARY KEY, ts TIMESTAMPTZ NOT NULL DEFAULT now(), subject_id INT NOT NULL, resource_type VARCHAR(128), resource_id VARCHAR(128), action VARCHAR(64) NOT NULL, decision BOOLEAN NOT NULL, matched_policy_id INT REFERENCES abac_policies(id), context_snapshot JSONB -- snapshot subject+resource attrs на момент решения ); CREATE INDEX idx_abac_audit_subject ON abac_audit_log (subject_id, ts DESC); CREATE INDEX idx_abac_audit_resource ON abac_audit_log (resource_type, resource_id, ts DESC); 

Это даёт ответ на вопрос «почему пользователь X не смог сделать Y с объектом Z три дня назад» — без него расследование инцидентов превращается в гадание.

Комбинирование с RBAC

Чистый ABAC медленнее RBAC при большом числе политик — каждая проверка проходит через все правила. На практике используют гибрид: RBAC как первый слой (быстрая грубая проверка по роли), ABAC как второй (тонкие контекстуальные правила только там, где нужно).

async function authorize(user, resource, action) { // Быстрый RBAC-check: есть ли у роли хоть какой-то доступ к этому типу ресурса? if (!await rbac.canAccessResourceType(user.role, resource.type)) { return false; // отсекаем без загрузки объекта и прохода по ABAC-политикам } // Тонкая проверка через ABAC return engine.evaluate(user, resource, action); } 

Как оценить сложность проекта?

Сроки зависят от объёма политик и архитектуры. Мы выделяем три варианта:

Вариант Срок Что входит
Базовый 3–4 дня Движок в коде, 5–10 политик, тесты
Расширенный 7–10 дней Политики в БД, REST API, UI для редактирования, аудит
Интеграция с OPA 2–3 дня Sidecar-развёртывание, написание политик на Rego, тестирование

Что входит в работу по внедрению ABAC?

  • Анализ модели доступа и атрибутов пользователей, ресурсов, окружения.
  • Проектирование и документирование политик доступа.
  • Разработка движка принятия решений (или интеграция с OPA/Casbin).
  • Реализация REST API для управления политиками.
  • Создание системы аудита с визуализацией логов.
  • Покрытие тестами (unit + integration).
  • Деплой и настройка мониторинга.
  • Обучение команды: как писать и отлаживать политики.
  • Гарантия на код и поддержка после внедрения.

Базовый движок с хранением политик в коде — 3–4 дня. Движок с хранением политик в базе и UI для их редактирования — 7–10 дней. Добавление audit log с UI — ещё 2–3 дня. Интеграция со сторонней PDP (Open Policy Agent, Casbin) вместо самописного движка — 2–3 дня на интеграцию плюс время на написание политик на Rego или PERM.

Open Policy Agent — зрелая альтернатива самописному движку. Политики пишутся на Rego, OPA запускается как sidecar или как отдельный сервис, приложение обращается к нему через HTTP или gRPC. Это добавляет операционную сложность, но даёт версионирование политик, горячую перезагрузку и встроенный аудит.

Если у вас сложные требования к доступу — обратитесь к нам за аудитом. Оценим ваш проект бесплатно. Свяжитесь с нами, чтобы обсудить детали. Закажите реализацию ABAC под ключ.