Перейти к содержимому
DedicatedPHP Контакт

Проверяемая авторизация в PHP: права без исключений

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

Редакционная схема авторизации в PHP, связывающая роли, разрешения, организационный контекст и защищённые ресурсы

Проектирование прав и авторизации в PHP не сводится к экрану, где назначаются роли. Проблема возникает, когда одно и то же действие зависит от того, кто его выполняет, от имени какой организации действует пользователь, над какими данными он действует и в каком состоянии находятся эти данные. Если эти условия распределены между контроллерами, запросами, шаблонами и проверками интерфейса, система в итоге накапливает исключения, которые сложно проверять.

Цель состоит в том, чтобы каждое решение было явным, воспроизводимым и проверяемым: субъект пытается выполнить операцию над ресурсом в некотором контексте, а политика решает, разрешено ли это. Такой подход преобразует неоднозначные операционные правила в технические контроли, которые продуктовая команда, операционный отдел и разработчики могут проверять совместно.

Разделяйте идентичность, авторизацию и область данных

Разделяйте идентичность, авторизацию и область данных — guía visual de DedicatedPHP

Аутентификация отвечает на вопрос, кем является пользователь: сессия, учётные данные, провайдер идентичности или токен. Авторизация отвечает на вопрос, что может делать эта идентичность. Не следует выводить второе только из первого или рассматривать их как единый слой.

Роль объединяет обязанности, например администратора организации, агента поддержки или утверждающего. Разрешение представляет конкретную операцию, например invoice.read, invoice.approve или member.invite. Область действия определяет, к каким ресурсам применяется эта операция: счетам организации, делам подразделения или собственным записям.

Это различие предотвращает распространённую ошибку: предоставить разрешение на чтение счетов и предположить, что оно позволяет читать любой счёт. Политика всё равно должна проверить, принадлежит ли ресурс активной организации, назначено ли пользователю соответствующее подразделение и допускает ли состояние ресурса запрошенное действие.

Стройте матрицу доступа на основе операций

Прежде чем выбирать классы или пакеты, перечислите реальные ресурсы и операции. Используйте бизнес-глаголы вместо расплывчатых меток вроде «управлять»: создать заказ, просмотреть заказ, исправить черновик, утвердить заказ, отменить заказ, экспортировать заказы или изменить участников.

Для каждой операции согласуйте с бизнесом четыре элемента:

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

Полученная матрица — не код авторизации, а спецификация, доступная для проверки. Кроме того, она заставляет выявлять незавершённые решения. Если указано, что поддержка может «просматривать заказы», необходимо уточнить, может ли она видеть персональные данные, вложенные документы, закрытые заказы или сведения всех организаций.

Предпочитайте небольшие и стабильные действия

Слишком широкое действие концентрирует привилегии и затрудняет применение принципа наименьших привилегий. Разделение order.read и order.export либо user.update и user.assign_role позволяет предоставлять доступ точно. Также не следует создавать разрешение для каждого частного случая: если различие зависит от ресурса, обычно это условие политики, а не новая роль.

Выбирайте между ролями, разрешениями, атрибутами и контекстом

Простые роли работают, когда стабильных профилей немного и операции почти не зависят от данных. Это хорошая отправная точка, но они становятся хрупкими при появлении названий вроде manager_con_exportacion или supervisor_solo_unidad_norte. Такие комбинации кодируют исключения как постоянные профили.

Явные разрешения подходят для отделения обязанностей от профилей и для управляемого назначения возможностей. Атрибуты полезны, когда решение зависит от свойств субъекта, ресурса или среды: организации, подразделения, классификации, владельца, страны или уровня риска. Контекстные правила дополняют модель, когда участвуют временные условия, например активное делегирование или этап утверждения.

На практике гибридная модель обычно более поддерживаема: роли предоставляют базовые разрешения; политика оценивает атрибуты пользователя и ресурса; а контекст предоставляет выбранную организацию или канал операции. Роль не должна заменять анализ данных.

Централизуйте политики и фильтруйте данные в источнике

PHP-приложению нужна единая точка для выражения решений. Она может быть реализована в классах политик, сервисах авторизации или эквивалентных компонентах выбранного фреймворка. Важно, чтобы контроллеры запрашивали решение, а представления не были единственным барьером.

if (!$authorizer->can($actor, 'order.approve', $order, $context)) {
    throw new AccessDeniedException();
}

Политика должна получать только данные, необходимые для принятия решения: идентичность, операцию, ресурс и контекст. Избегайте обращения к глобальным переменным или неявной зависимости от текущего маршрута; это затрудняет тестирование и повторное использование правил.

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

Состояния и переходы как часть политики

Чувствительные операции часто зависят от состояния. Утверждающий может утвердить ожидающий заказ, но не отменённый и не уже утверждённый. Явно моделируйте разрешённый переход и повторно выполняйте проверку в точке, которая сохраняет изменение. Интерфейс может отключить кнопку для ориентира, но эффективным контролем является серверная политика.

Избегайте постоянных исключений и раскрывающих отказов

Обобщённым ролям, таким как «администратор», нужны чёткие границы. Администратор организации не должен автоматически становиться администратором платформы. Аналогично, исключение вроде «может редактировать эту конкретную запись» должно иметь владельца, причину, дату проверки или срок действия и прослеживаемость. Если оно повторяется, вероятно, не хватает бизнес-правила или атрибута модели.

Отказы должны быть полезными, не раскрывая чувствительную информацию. При прямом запросе к чужому ресурсу обычно предпочтителен ответ, неотличимый от случая, когда ресурс не существует. При действии над уже видимым ресурсом можно указать, что не хватает разрешений, не раскрывая внутренние правила, назначения или защищённые атрибуты.

Регистрируйте разрешённые и отклонённые чувствительные действия, когда это приносит операционную пользу: изменения ролей, экспорты, утверждения, делегированный доступ и изменения конфигурации. Аудит должен включать действующее лицо, действие, ресурс, организацию или контекст, время и результат. Не регистрируйте учётные данные, токены или ненужные персональные данные.

Тестируйте авторизацию как свойство продукта

Тесты авторизации должны покрывать разрешённые и отклонённые решения. Минимальный набор включает: пользователя с разрешением для своей организации; того же пользователя в другой организации; пользователя без разрешения; ресурс в недопустимом состоянии; и изменение контекста, например отзыв назначения или завершение делегирования.

Тестируйте политики напрямую, поскольку они дают точную диагностику, и добавляйте интеграционные тесты, чтобы подтвердить, что маршруты, контроллеры, запросы и операции записи применяют решение. Наиболее опасны регрессии привилегий: добавление роли, маршрута или оптимизации запроса, непреднамеренно расширяющее доступ.

  • Проверьте, что список не содержит ресурсов вне области действия.
  • Проверьте, что знание чужого идентификатора не предоставляет доступа.
  • Проверьте, что изменение состояния требует соответствующей политики.
  • Проверьте, что отзыв разрешения аннулирует возможность в следующем запросе.

Внедряйте модель в приложении с распределёнными правилами

Не нужно переписывать всю систему. Начните с инвентаризации маршрутов, команд, запланированных задач и точек экспорта, которые изменяют или раскрывают данные. Отдайте приоритет действиям с высоким влиянием и ресурсам, совместно используемым организациями. Выделите политику для каждого домена, покройте текущее поведение тестами и исправьте правила, предоставляющие больше доступа, чем предполагалось.

Затем замените распределённые проверки вызовами сервиса авторизации и перенесите фильтрацию области действия в запросы. Периодически проверяйте неиспользуемые разрешения, роли со слишком многими возможностями, истёкшие делегирования и активные исключения. Проектирование прав и авторизации в PHP станет поддерживаемым, когда новая функциональность сможет до начала разработки ответить, кто выполняет операцию, над каким ресурсом, при каких условиях и какими доказательствами это проверено.

Контрольный список для каждого нового модуля

Контрольный список для каждого нового модуля — guía visual de DedicatedPHP
  • Определены ли бизнес-операции и их ресурсы?
  • Различает ли матрица разрешение, область действия и условие состояния?
  • Применяются ли политики при чтении, записи, экспорте и неинтерактивных процессах?
  • Фильтруют ли запросы данные до передачи их в интерфейс?
  • Есть ли тесты разрешённого, отклонённого и межорганизационного доступа?
  • Оставляют ли чувствительные действия соразмерный и безопасный аудиторский след?
Хотите применить эти идеи в своем проекте?Давайте обсудим вашу PHP-платформу.
Посмотреть связанные услуги