WP REST API часто оставляют открытым «на всякий случай», а потом удивляются лишним запросам к /wp-json/, светящимся endpoint’ам в сканерах и нежелательным утечкам структуры сайта. При этом полностью рубить REST API нельзя: редактор блоков, админка и часть плагинов на нём завязаны напрямую.
Нормальная задача здесь не «выключить всё», а закрыть REST API для гостей и оставить его доступным для авторизованных пользователей и нужных интеграций. Ниже — рабочая схема без выдуманных хуков и без ломки типового WordPress.
Когда это действительно нужно
Ограничение REST API имеет смысл, если вы видите один или несколько симптомов:
- в логах много запросов к
/wp-json/от ботов и сканеров; - внешним сервисам не нужен публичный доступ к данным сайта;
- вы хотите уменьшить поверхность атаки и убрать лишнюю «разведку» по структуре контента;
- на сайте нет публичных SPA/мобильных приложений, которым нужен открытый REST;
- проверка безопасности показывает открытые endpoint’ы, которые не используются по делу.
Если у вас есть публичный каталог, headless-часть, мобильное приложение или интеграция с внешним сервисом, закрывать REST API «в лоб» нельзя. В этом случае ограничивают только отдельные маршруты или делают whitelist.
Диагностика: что именно открыто
Сначала проверьте, что реально отдаёт сайт. На обычной установке WordPress публичный REST API отвечает на /wp-json/ и на маршруты вида /wp-json/wp/v2/posts.
curl -I https://example.com/wp-json/Если сервер отвечает 200 OK или 301/302 с последующим доступом к JSON, значит endpoint доступен. Это ещё не проблема само по себе, но повод проверить, нужен ли он гостям.
Полезно посмотреть, кто и как обращается к API:
- access log веб-сервера;
- логи WAF/Cloudflare, если они есть;
- запросы из браузера на странице с фронтендом;
- ошибки в консоли, если какой-то плагин ожидает REST и не получает ответ.
Что нельзя делать вслепую
Не ставьте плагины, которые «отключают REST API целиком», не проверив зависимости. Частая поломка выглядит так: редактор блоков открывается, но не сохраняет записи; в админке перестают работать автосохранение, поиск медиа или метабоксы плагинов.
Рабочее решение: закрыть REST API для неавторизованных пользователей
Самый предсказуемый вариант — запретить доступ к REST API для гостей через фильтр rest_authentication_errors. Он существует в ядре WordPress и позволяет вернуть ошибку до выполнения маршрута.
Добавьте код в functions.php дочерней темы или в небольшой mu-plugin. Для продакшена mu-plugin обычно надёжнее: он не зависит от темы.
<?php
add_filter( 'rest_authentication_errors', function( $result ) {
if ( ! empty( $result ) ) {
return $result;
}
if ( is_user_logged_in() ) {
return $result;
}
// Разрешаем только базовую проверку REST, но закрываем данные для гостей.
return new WP_Error(
'rest_forbidden',
__( 'REST API доступен только авторизованным пользователям.', 'textdomain' ),
array( 'status' => 401 )
);
} );Что делает этот код:
- не мешает уже существующим ошибкам и проверкам;
- пропускает авторизованных пользователей;
- для гостей возвращает
401 Unauthorized.
Если вам нужно оставить доступ для конкретных маршрутов, добавьте исключение по URI.
<?php
add_filter( 'rest_authentication_errors', function( $result ) {
if ( ! empty( $result ) ) {
return $result;
}
$request_uri = isset( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : '';
// Разрешаем, например, публичный endpoint для формы обратной связи.
if ( str_contains( $request_uri, '/wp-json/contact-form-7/' ) ) {
return $result;
}
if ( is_user_logged_in() ) {
return $result;
}
return new WP_Error( 'rest_forbidden', 'REST API закрыт для гостей.', array( 'status' => 401 ) );
} );Это не идеальный универсальный whitelist, но для точечной задачи работает. Если у вас несколько публичных маршрутов, лучше перечислить их явно и документировать, зачем каждый нужен.
Альтернативы: плагин, код или сервер
Если не хочется править код вручную, можно использовать плагин для точечной оптимизации и чистки сайта. Например, Clearfy Pro умеет закрывать лишние технические сущности WordPress и удобен, когда вы одновременно наводите порядок в SEO и служебных настройках. Но если задача узкая и вам нужен полный контроль, код обычно прозрачнее.
| Подход | Плюсы | Минусы |
|---|---|---|
Код через rest_authentication_errors | Точный контроль, без лишних зависимостей | Нужно аккуратно протестировать исключения |
| Плагин оптимизации | Быстро включить, удобно для типовых сайтов | Меньше гибкости, возможны лишние опции |
| Блокировка на сервере/WAF | Снимает нагрузку раньше WordPress | Сложнее поддерживать исключения и интеграции |
Проверка результата после внедрения
После добавления кода проверьте не только главную страницу, но и реальные сценарии.
- Откройте
/wp-json/в браузере в режиме инкогнито. Для гостя должен быть отказ. - Проверьте вход в админку и открытие редактора записей.
- Создайте или отредактируйте запись в Gutenberg и убедитесь, что автосохранение работает.
- Если есть формы, интеграции или мобильное приложение, проверьте их отдельно.
- Посмотрите логи на предмет новых ошибок
401и403.
Быстрая CLI-проверка выглядит так:
curl -i https://example.com/wp-json/Для гостя вы должны увидеть не JSON с данными, а отказ. Если вместо этого всё ещё приходит содержимое API, значит код не загрузился, фильтр подключён не туда или его перебивает другой плагин.
Частые ошибки и как их исправить
Сломался редактор блоков
Обычно это значит, что REST API закрыли слишком грубо: через .htaccess, nginx-правило или плагин, который режет весь /wp-json/ без исключений. Верните доступ авторизованным пользователям и проверьте, не блокируется ли admin-ajax.php отдельно.
Плагин перестал синхронизировать данные
Некоторые плагины используют REST API для фоновых запросов. Если после ограничения что-то перестало работать, найдите конкретный маршрут и добавьте исключение, а не открывайте всё целиком.
Получается 403 вместо 401
Это не критично, но важно понимать источник. 401 обычно возвращает сам WordPress через ваш фильтр, а 403 может приходить от WAF, сервера или другого плагина безопасности. Смотрите заголовки ответа и логи.
Ограничение поставили в теме, а потом сменили дизайн
Если код лежит в теме, при смене темы защита исчезнет. Для технических ограничений лучше использовать mu-plugin или отдельный мини-плагин.
Безопасность и производительность: что ещё стоит учесть
Закрытие REST API для гостей не заменяет нормальную защиту входа, обновления ядра и плагинов, а также ограничение лишних endpoint’ов. Но как часть общей гигиены это полезно: меньше публичной поверхности, меньше шума в логах, меньше случайных запросов к серверу.
Если вы одновременно чистите сайт от технического мусора, имеет смысл проверить и другие вещи: открытые sitemap, лишние эмодзи-скрипты, XML-RPC, дубли архивов и служебные страницы. На проектах, где нужен более широкий набор технических правок, обычно удобнее делать это через один инструмент, а не набор разрозненных сниппетов.
- храните технические сниппеты в отдельном mu-plugin;
- не закрывайте REST API на боевом сайте без теста в staging;
- ведите список исключённых маршрутов и причин, почему они открыты;
- после обновлений плагинов повторно проверяйте критичные интеграции.
Если нужен более широкий набор настроек для чистки WordPress, иногда проще собрать это в одном месте, чем поддерживать десяток разрозненных правок. Но даже в этом случае правило одно: сначала проверка зависимостей, потом отключение.