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

Прежде чем выбирать поля или технологии, определите, какие задачи должен решать поиск: находить заказ по номеру, учётную запись по адресу электронной почты или обращения по статусу. Для каждой задачи укажите, кто её выполняет и какие записи может просматривать. Не определяйте область поиска как «всё, что есть в таблице»: например, сотруднику поддержки может требоваться доступ к определённым клиентам, а администратору — возможность работать с другим набором записей.
Преобразуйте эти правила в понятную модель авторизации: по организации, команде, владельцу, региону или другой сущности предметной области. Также определите, может ли доступ меняться со временем и что происходит, если пользователь теряет права, пока его сессия остаётся открытой. Интерфейс может скрывать опции, но действующее правило необходимо проверять на сервере.
Задайте явные фильтры и проверяйте каждый критерий
Составьте ограниченный список полей, по которым разрешён поиск, и типов фильтров. Например, форма может поддерживать точное совпадение по номеру, выбор статуса из списка и диапазон дат. Не превращайте любой параметр, переданный клиентом, в имя столбца, условие SQL или критерий доступа.
Проверяйте значения на сервере: форматы, длину, диапазоны, допустимые значения и сочетания параметров. Используйте подготовленные запросы, чтобы отделить значения от SQL-запроса. Однако подготовленные параметры сами по себе не защищают динамические имена столбцов и условия сортировки: такие элементы должны выбираться из списка, заданного на сервере.
Бизнес-фильтры и условия авторизации — разные вещи. Пользователь может запросить «статус — ожидает обработки», но не должен иметь возможности передать идентификатор организации, чтобы расширить свою область доступа. Рассчитывайте эту область на основе аутентифицированной учётной записи и действующих правил, а не доверяйте изменяемым полям формы.
Применяйте авторизацию к строкам, счётчикам и связанным действиям
Условие доступа должно входить в запрос, который получает результаты. Получение записей с последующей фильтрацией в PHP может привести к раскрытию данных в логах, памяти, ответах или вспомогательных маршрутах, а также усложняет пагинацию и подсчёт. По возможности формируйте запрос так, чтобы условия авторизации и поисковые фильтры применялись вместе.
Проверяйте все связанные с поиском ответы. Общее количество результатов может раскрыть, сколько записей существует за пределами разрешённой области доступа; автоподсказки могут раскрыть имена или адреса электронной почты; при экспорте могут применяться правила, отличающиеся от правил экрана. Ссылки на страницы подробностей и массовые операции также должны учитывать область доступа. Если сам факт существования недоступной записи чувствителен, избегайте различий в ответах, позволяющих его определить.
Централизуйте формирование критериев доступа, если это помогает поддерживать их единообразие, но не считайте общую абстракцию автоматической авторизацией: убедитесь, что каждый запрос и маршрут используют её правильно.
Выберите между SQL и поисковым индексом
SQL обычно достаточно, если фильтры чётко определены, текстовая релевантность несложная, а база данных может выполнять запрос с подходящими индексами. Это прямой способ объединять точное совпадение, диапазоны, связи и разрешённые варианты сортировки. Прежде чем добавлять ещё один компонент, изучите план выполнения и индексы.
Поисковый индекс может пригодиться, если необходим поиск с учётом опечаток, лингвистический анализ, текстовая релевантность или поиск по большим объёмам данных, с которыми SQL не справляется в рамках требуемых операционных показателей. Однако индекс добавляет синхронизацию, задержки обновления, контроль доступа и дополнительные операционные задачи. Он не заменяет базу данных как источник достоверных сведений о правах доступа.
Если индекс содержит данные из нескольких областей доступа, ограничивайте запрос с учётом авторизации до возврата документов и продумайте, как распространяются изменения или отзыв прав. Для чувствительных действий повторно проверяйте доступ по источнику истины. Определите допустимую задержку и поведение системы, если индекс устарел или недоступен; альтернативой может быть временное отключение расширенного поиска, но не пропуск проверок.
Ограничьте нагрузку, сортировку и объём ответа
Установите максимальный размер страницы и используйте стабильную пагинацию. Для больших наборов данных или часто меняющихся результатов пагинация по курсору может решить часть проблем, связанных со смещением строк, однако для неё необходимы постоянный порядок сортировки и чётко определённые критерии продолжения.
Разрешайте сортировку только по предусмотренным полям и задавайте детерминированный дополнительный порядок, например по уникальному идентификатору. Ограничьте длину текстовых запросов, временные диапазоны и количество фильтров; не допускайте пустых запросов, запускающих ресурсоёмкое сканирование. Для тяжёлых операций предусмотрите ограничения частоты запросов и максимальное время выполнения. Поиск не должен возвращать поля, которые не нужны интерфейсу.
Проверяйте права доступа и граничные случаи
Добавьте позитивные и негативные тесты для разных профилей и областей доступа. Проверьте, что пользователи находят разрешённые записи и не могут получить остальные, изменяя фильтры, переходя по страницам, меняя сортировку или запрашивая страницу с подробностями. Добавьте сценарии с комбинированными фильтрами, недопустимыми значениями, пустыми результатами и записями, у которых изменился владелец или область доступа.
Проверяйте также счётчики, подсказки, экспорт и массовые операции. Полезный тест проверяет не только то, что чужая запись не отображается в списке, но и то, что её нельзя найти по точному номеру или обнаружить через вспомогательный ответ. При изменении прав убедитесь, что поведение обновляется в соответствии с заданной политикой.
Операционные метрики должны помогать диагностике, не создавая дополнительной утечки данных. Записывайте задержки, ошибки, объём результатов и тип операции, не сохраняя чувствительные поисковые запросы или ненужные персональные данные. Ограничьте доступ к таким логам и определите срок их хранения. Отдельно отслеживайте медленные запросы и ошибки индекса, чтобы отличать проблемы производительности от сбоев авторизации.
Контрольный список перед публикацией изменений

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



