Если достаточно заменить comment_id в запросе, чтобы изменить чужой комментарий, интерфейс скрывает кнопку, но backend не проверяет право на конкретный объект. Это классическая ошибка объектной авторизации: аутентификация пользователя есть, а связь пользователя с ресурсом не подтверждается.
Исправление выполняется на сервере. Комментарий нужно выбирать внутри разрешенной области пользователя или tenant, затем проверять роль, владельца и состояние объекта. Клиентский user_id и скрытая кнопка не являются доказательством права.
Что проверить в первую очередь
Сначала зафиксируйте точный сценарий, время ошибки и последнее известное рабочее состояние. Не меняйте несколько настроек одновременно: один контролируемый шаг должен подтверждать или исключать одну гипотезу. Перед работой с данными и конфигурацией подготовьте резервную копию и понятный способ отката.
- Снимите запрос редактирования и определите, какие идентификаторы принимает backend.
- Проверьте, может ли обычный пользователь изменить comment_id, author_id или tenant_id.
- Составьте матрицу прав: автор, модератор, администратор, удаленный и заблокированный комментарий.
- Проверьте REST, GraphQL, мобильный API и старые endpoint отдельно.
Почему возникает проблема
Внешний симптом обычно появляется на границе нескольких компонентов: интерфейса, backend, базы, фоновой очереди или внешнего сервиса. Поэтому важно найти первое место, где состояние становится неверным, а не исправлять последнее сообщение об ошибке.
- Backend выполняет UPDATE WHERE id=:id без условия owner/tenant.
- author_id принимается из тела запроса и не сверяется с текущей сессией.
- Администраторская проверка роли ошибочно срабатывает для любого авторизованного пользователя.
- Кеш решения доступа не включает user/tenant и переиспользуется между клиентами.
- Один endpoint защищен, а массовое редактирование или GraphQL mutation — нет.
Пошаговая диагностика
Диагностику проводите на тестовой записи или отдельном окружении. В журналах скрывайте токены, пароли и персональные данные. Для каждого шага сохраняйте измеримый результат: идентификатор события, код ответа, версию записи, состояние процесса или контрольную сумму.
- Создайте двух тестовых пользователей и комментарии в разных tenant.
- Попробуйте чтение, изменение, удаление и восстановление чужого объекта каждым маршрутом.
- Проверьте ORM scope и SQL, сформированный для обычного пользователя.
- Повторите тест после смены роли и выхода, исключая устаревший кеш прав.
- Проверьте audit log: он должен фиксировать actor и target, но не содержать лишний текст.
Объектная авторизация на стороне сервера
Правильная проверка отвечает не только на вопрос «кто вошел», но и «может ли этот субъект выполнить это действие над этим конкретным объектом сейчас».
- Обычный пользователь получает объект запросом WHERE id=? AND author_id=? AND tenant_id=?.
- Модератор проходит отдельную policy с ограниченной областью сообщества или проекта.
- Администраторское право не выводится из параметра запроса и проверяется по серверной роли.
- Удаленное, закрытое или архивное состояние может запрещать редактирование даже владельцу.
- Решение доступа вычисляется заново для операции изменения и не доверяет предыдущему чтению.
Как исправить проблему
Исправление лучше разбить на небольшие обратимые изменения. Сначала устраните подтвержденную причину, затем повторите исходный сценарий и проверьте соседние функции. Массовую обработку данных запускайте на ограниченной выборке с отчетом и только после сверки расширяйте на весь объем.
- Вынесите правила в policy/authorization service и примените ко всем операциям.
- Фильтруйте выборку по текущему user и tenant до выполнения UPDATE.
- Игнорируйте author_id из клиента при обычном редактировании.
- Исправьте ключ кеша прав или не кешируйте чувствительное решение без строгого контекста.
- Добавьте единый ответ 404/403 согласно модели раскрытия существования объекта.
Безопасный порядок внедрения
- Сохраните затрагиваемые данные, конфигурацию и текущие журналы, заранее проверив способ отката.
- Повторите проблему на тестовом объекте без реальных списаний, рассылок и изменений клиентских данных.
- Внесите одно логическое изменение и зафиксируйте его в системе контроля версий или журнале работ.
- Не отключайте авторизацию, валидацию, шифрование и другие защитные механизмы ради быстрого исчезновения ошибки.
- После выкладки контролируйте логи, метрики и полный пользовательский сценарий, а не только один успешный запрос.
Как проверить результат
Разовый успешный тест недостаточен. Повторите операцию, проверьте крайние значения, параллельные действия и восстановление после перезапуска или временного сбоя. Для важного сценария сохраните автоматический тест либо короткий регрессионный чек-лист.
- Автор редактирует свой комментарий, но не чужой даже при подмене ID.
- Модератор действует только в разрешенной области, а пользователь другого tenant не видит объект.
- Массовый endpoint и GraphQL mutation подчиняются тем же policy.
- После смены роли старый токен или кеш не сохраняет прежние привилегии.
Типичные ошибки при исправлении
- Исправлять только отображение кнопки во frontend.
- Сравнивать owner с user_id, присланным самим клиентом.
- Выдавать подробный чужой объект до проверки права.
- Проверять право только при чтении, но не при update/delete.
Как предотвратить повторение
Профилактика строится вокруг явных контрактов, повторяемых релизов и наблюдаемости. Система должна не только работать сейчас, но и позволять быстро увидеть нарушение инварианта при следующем обновлении, росте нагрузки или сбое внешнего сервиса.
- Создайте матрицу ролей и негативные integration-тесты для каждого объекта.
- Используйте scoped repositories, которые требуют actor/tenant.
- Проводите code review всех endpoint с прямым ID ресурса.
- Мониторьте необычные последовательные обращения к множеству чужих ID.
Что подготовить для технического разбора
- Описание ожидаемого и фактического поведения, а также точную последовательность действий.
- Время проблемы, идентификатор тестового объекта и версии затронутых компонентов.
- Фрагменты журналов до и после ошибки без секретов и персональных данных.
- Перечень последних изменений и уже выполненных проверок.
- Безопасный доступ к тестовой среде или способ воспроизвести сбой без влияния на клиентов.
Частые вопросы
Что лучше возвращать: 403 или 404?
Оба варианта возможны. 404 уменьшает раскрытие существования чужого объекта, 403 явно сообщает о запрете. Важно выбрать последовательную модель.
Достаточно ли UUID вместо числового ID?
Нет. Непредсказуемый ID усложняет перебор, но не заменяет проверку права на объект.
Когда нужна помощь специалиста
Если в API можно менять чужие комментарии или другие записи подменой ID, я могу проверить объектную авторизацию, исправить policy и добавить негативные тесты для ролей, tenant и альтернативных endpoint.