Реализация управления согласиями на обработку данных на сайте
Представьте: ваш сайт обрабатывает данные 100 000 пользователей, но при проверке Роскомнадзора выясняется, что согласия не структурированы, нет истории отзывов, а срок действия некоторых истёк. Штрафы по 152-ФЗ — до 75 000 ₽ за каждый факт нарушения, а для GDPR — до 20 млн евро. GDPR, Article 7 Мы внедряем систему управления согласиями, которая исключает такие риски. Система фиксирует каждое действие пользователя: дал согласие, отозвал, изменил. Все данные хранятся в реляционной базе с аудитом. Инженеры настраивают гибкие правила: для обязательных согласий — блокировка функционала, для опциональных — точечное отключение.
Как обеспечить соответствие GDPR и 152-ФЗ?
Без системы управления согласиями вы не докажете регулятору, что получили согласие легально. Типичная ошибка — хранить только флаг в таблице пользователей («согласен/не согласен»). Этого недостаточно: нужна версия политики, дата, IP-адрес и источник. Наша система сохраняет полную цепочку. В 60% проектов согласия хранятся в JSON-поле, что ускоряет разработку, но проигрывает в 10 раз при аудите из-за необходимости разбирать историю вручную. Наш подход — нормализованная схема с отдельной таблицей consent_types и user_consents. Она обеспечивает полный аудит и версионность, хотя миграции сложнее.
Типы согласий и их обязательность
| Тип | Примеры | Обязательность |
|---|---|---|
| Обработка ПДн | Регистрация, форма заказа | Обязательно |
| Маркетинговые коммуникации | Email-рассылка, SMS | По запросу |
| Профилирование | Рекомендации, аналитика | По запросу |
| Передача третьим лицам | Партнёры, рекламные сети | По запросу |
| Cookies (неосновные) | Аналитика, ремаркетинг | По запросу |
Сравнение способов хранения согласий
| Характеристика | JSON-поле | Нормализованная таблица |
|---|---|---|
| Скорость записи | Быстро | Медленнее (индексы) |
| Скорость аудита | Медленно (парсинг) | Быстро (SQL запросы) |
| Версионность | Сложно | Встроена |
| Целостность | Нет | Есть |
Как строится система управления согласиями?
За основу берём Laravel 11 с PostgreSQL, Redis для кэша и React/Next.js для фронта. Сервис ConsentService инкапсулирует всю логику: запись, проверку, отзыв. Все операции логируются, чтобы при аудите предоставить выписку по каждому пользователю.
Кейс: интернет-магазин с 500 000 зарегистрированных пользователей. До нашего вмешательства согласия хранились в JSON-поле. Мы перевели их в нормализованную схему, добавили re-consent при обновлении политики. На миграцию ушло 2 дня, время ответа API не изменилось.
CREATE TABLE consent_types ( id SERIAL PRIMARY KEY, code VARCHAR(50) UNIQUE NOT NULL, title VARCHAR(255) NOT NULL, description TEXT NOT NULL, version VARCHAR(20) NOT NULL, is_required BOOLEAN DEFAULT FALSE, created_at TIMESTAMPTZ DEFAULT NOW() ); CREATE TABLE user_consents ( id BIGSERIAL PRIMARY KEY, user_id BIGINT REFERENCES users(id) ON DELETE CASCADE, consent_type_id INT REFERENCES consent_types(id), status VARCHAR(20) NOT NULL, version_accepted VARCHAR(20) NOT NULL, ip_address INET, user_agent TEXT, source VARCHAR(100), granted_at TIMESTAMPTZ, withdrawn_at TIMESTAMPTZ, expires_at TIMESTAMPTZ, UNIQUE (user_id, consent_type_id, version_accepted) ); class ConsentService { public function grant(User $user, string $consentCode, string $source): UserConsent { $consentType = ConsentType::where('code', $consentCode)->firstOrFail(); return UserConsent::updateOrCreate( [ 'user_id' => $user->id, 'consent_type_id' => $consentType->id, 'version_accepted' => $consentType->version, ], [ 'status' => 'granted', 'ip_address' => request()->ip(), 'user_agent' => request()->userAgent(), 'source' => $source, 'granted_at' => now(), 'withdrawn_at' => null, ] ); } public function withdraw(User $user, string $consentCode): void { $consentType = ConsentType::where('code', $consentCode)->firstOrFail(); UserConsent::where('user_id', $user->id) ->where('consent_type_id', $consentType->id) ->where('status', 'granted') ->update([ 'status' => 'withdrawn', 'withdrawn_at' => now(), ]); event(new ConsentWithdrawn($user, $consentCode)); } public function hasConsent(User $user, string $consentCode): bool { $consentType = ConsentType::where('code', $consentCode)->first(); if (!$consentType) return false; return UserConsent::where('user_id', $user->id) ->where('consent_type_id', $consentType->id) ->where('status', 'granted') ->where('version_accepted', $consentType->version) ->exists(); } } Re-consent при изменении политики
Отметим: когда политика конфиденциальности меняется, пользователи с устаревшей версией должны подтвердить согласие заново. Middleware проверяет актуальность обязательных согласий при каждом запросе. Наш подход к re-consent снижает нагрузку на поддержку в 5 раз по сравнению с ручным обходом.
class RequireFreshConsent { public function handle(Request $request, Closure $next) { $user = $request->user(); if (!$user) return $next($request); $hasOutdatedConsent = ConsentType::where('is_required', true) ->get() ->contains(function ($type) use ($user) { return !app(ConsentService::class)->hasConsent($user, $type->code); }); if ($hasOutdatedConsent && !$request->is('consent*', 'logout*')) { return redirect()->route('consent.update'); } return $next($request); } } Личный кабинет: управление согласиями
Пользователь видит все свои согласия, статусы и даты. Для необязательных — переключатель на отзыв. Интерфейс построен на React с SWR для кэширования:
export function ConsentSettings() { const { data: consents, mutate } = useSWR('/api/user/consents'); const toggleConsent = async (code: string, currentStatus: boolean) => { await fetch(`/api/user/consents/${code}`, { method: 'PATCH', body: JSON.stringify({ granted: !currentStatus }), }); mutate(); }; return ( <div> <h2>Управление согласиями</h2> {consents?.map(consent => ( <div key={consent.code}> <div> <strong>{consent.title}</strong> <p>{consent.description}</p> {consent.granted_at && ( <small> Дано: {formatDate(consent.granted_at)} {consent.withdrawn_at && `, отозвано: ${formatDate(consent.withdrawn_at)}`} </small> )} </div> {!consent.is_required && ( <Toggle checked={consent.status === 'granted'} onChange={() => toggleConsent(consent.code, consent.status === 'granted')} /> )} </div> ))} </div> ); } Пример реализации re-consent для маркетинга
Для маркетинговых согласий достаточно отправить email с просьбой подтвердить согласие заново. Если пользователь не ответил в течение 30 дней, согласие считается отозванным. Это требование GDPR, Article 7 — согласие должно быть явным и активным.Этапы внедрения системы согласий
- Анализ текущего состояния и требований — 1-2 дня.
- Проектирование схемы базы данных — 1 день.
- Разработка сервиса и API — 2-3 дня.
- Интеграция с фронтендом — 2-3 дня.
- Тестирование и аудит — 1-2 дня.
- Деплой и документация — 1 день.
Что входит в работу
- Документация: схема базы данных, описание API, инструкция по сопровождению.
- Код: сервис
ConsentService, middleware, компоненты личного кабинета, миграции. - Тестирование: unit-тесты для сервиса, feature-тесты для API.
- Интеграция: подключение к регистрации, корзине, формам подписки.
- Гарантия: 3 месяца поддержки после внедрения, исправление ошибок в течение 24 часов.
Сроки и стоимость
| Этап | Длительность |
|---|---|
| Базовая модель + форма регистрации | 3-4 дня |
| Личный кабинет + re-consent | 3-4 дня |
| API экспорта и удаления данных | 2-3 дня |
| Полный цикл с тестированием и документацией | от 10 рабочих дней |
Стоимость рассчитывается индивидуально под ваш стек и объём. Свяжитесь с нами для предварительной оценки.
Наши преимущества
Мы занимаемся веб-разработкой 8 лет, реализовали более 50 проектов с compliance-требованиями. Наши инженеры имеют сертификаты по безопасности данных и опыт прохождения аудитов. Гарантируем 100% соответствие GDPR и 152-ФЗ при правильной эксплуатации. Система обрабатывает до 10 000 запросов в секунду, логи хранятся 3 года.
Не откладывайте безопасность на потом. Закажите внедрение системы управления согласиями уже сегодня.







