REST API в WordPress часто оставляют открытым по умолчанию, а потом удивляются лишним запросам, светящимся публичным эндпоинтам и данным, которые не должны быть доступны анонимно. Полностью отключать API обычно плохая идея: редактор, блоки, некоторые плагины и фронтенд-скрипты могут зависеть от него. Рабочий сценарий — ограничить доступ для гостей, но сохранить авторизованные запросы и те эндпоинты, которые реально нужны сайту.
Когда REST API стоит ограничить
Это имеет смысл, если вы видите в логах регулярные обращения к /wp-json/ от ботов, хотите уменьшить поверхность атаки или закрыть служебные данные, которые не нужны посетителям. На небольших сайтах REST API нередко используется только внутри админки и редактора блоков. В таком случае можно запретить анонимный доступ и проверить, не завязаны ли на API темы, формы, поисковые фильтры или кастомные виджеты.
Что именно мы не трогаем
Мы не отключаем REST API целиком и не режем запросы для авторизованных пользователей. Это важно, потому что Gutenberg, редактор записей и часть плагинов работают через REST. Если вы просто заблокируете все запросы без исключений, получите неочевидные ошибки в админке и поломку интерфейса редактирования.
Диагностика проблемы перед изменениями
Сначала проверьте, используется ли REST API на сайте не только в админке. Откройте фронтенд и посмотрите исходный код страницы: если там есть скрипты, которые ходят в /wp-json/, их нужно учитывать. Затем проверьте консоль браузера и сетевые запросы на страницах с формами, фильтрами, поиском и динамической подгрузкой контента.
Полезно также посмотреть, какие эндпоинты реально доступны гостям. Самый простой тест — открыть https://example.com/wp-json/ в браузере без авторизации. Если ответ отдается публично, это нормально для стандартной установки, но не всегда нужно для вашего проекта.
- Проверьте фронтенд-страницы с интерактивными блоками.
- Откройте консоль браузера и убедитесь, что нет ошибок запросов к REST API.
- Посмотрите логи веб-сервера на частые обращения к
/wp-json/. - Проверьте, не использует ли сайт мобильное приложение, headless-часть или внешние интеграции.
Как ограничить REST API для гостей
Самый предсказуемый способ — повесить фильтр rest_authentication_errors и разрешить доступ только авторизованным пользователям. При этом можно сделать исключения для конкретных маршрутов, если они нужны публично. Ниже пример, который блокирует REST API для гостей, но не мешает входу в админку и авторизованным запросам.
<?php
add_filter( 'rest_authentication_errors', function( $result ) {
if ( ! empty( $result ) ) {
return $result;
}
if ( is_user_logged_in() ) {
return $result;
}
// Разрешаем только нужные публичные маршруты, если они есть.
$request_uri = isset( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : '';
if ( strpos( $request_uri, '/wp-json/' ) === false ) {
return $result;
}
return new WP_Error(
'rest_forbidden',
__( 'REST API доступен только авторизованным пользователям.', 'textdomain' ),
array( 'status' => 401 )
);
} );Этот вариант достаточно прямой, но его нужно применять аккуратно. Если у вас есть публичные эндпоинты, например для формы обратной связи или внешнего сервиса, их лучше разрешить отдельно, а не блокировать всё подряд.
Если нужно оставить отдельные публичные маршруты
Когда сайт использует один-два публичных маршрута, удобнее проверять не весь URI, а конкретный namespace или route. Это уже зависит от вашего кода и плагинов. В таком случае логика должна быть точечной: разрешаем нужное, остальное закрываем.
<?php
add_filter( 'rest_authentication_errors', function( $result ) {
if ( ! empty( $result ) || is_user_logged_in() ) {
return $result;
}
$route = isset( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : '';
$allowed_routes = array(
'/wp-json/myplugin/v1/public-form',
'/wp-json/myplugin/v1/status',
);
foreach ( $allowed_routes as $allowed ) {
if ( strpos( $route, $allowed ) !== false ) {
return $result;
}
}
if ( strpos( $route, '/wp-json/' ) !== false ) {
return new WP_Error( 'rest_forbidden', 'REST API закрыт для гостей.', array( 'status' => 401 ) );
}
return $result;
} );Что выбрать: код, плагин или серверное правило
| Подход | Плюсы | Минусы | Когда брать |
|---|---|---|---|
Код через rest_authentication_errors | Точечный контроль, можно делать исключения | Нужно тестировать совместимость | Если нужен гибкий вариант без лишних плагинов |
| Плагин безопасности | Удобно для админов без кода | Может дать слишком грубое ограничение | Если на сайте уже есть security-плагин и не хочется править тему |
| Правило на сервере | Быстро режет доступ на уровне веб-сервера | Легко сломать нужные маршруты | Если вы точно знаете, какие URL должны быть закрыты |
Если вы уже используете Clearfy Pro, имеет смысл сначала проверить, не решается ли задача его настройками для SEO и чистки сайта: Clearfy Pro. Но даже в этом случае логику исключений лучше перепроверить вручную, особенно если на сайте есть кастомные интеграции.
Пошаговое внедрение без лишнего риска
Не вставляйте код сразу в functions.php активной темы, если у вас часто меняется шаблон. Надёжнее использовать мини-плагин или mu-plugin. Так правило не пропадёт после обновления темы.
- Сделайте резервную копию файлов и базы.
- Проверьте, какие страницы и плагины используют REST API.
- Добавьте фильтр в mu-plugin или отдельный плагин.
- Очистите кеш, если используется page cache или CDN.
- Протестируйте вход в админку, редактор записей и публичные формы.
Пример минимального mu-plugin:
<?php
/**
* Plugin Name: REST API Restrict for Guests
*/
add_filter( 'rest_authentication_errors', function( $result ) {
if ( ! empty( $result ) || is_user_logged_in() ) {
return $result;
}
if ( isset( $_SERVER['REQUEST_URI'] ) && strpos( wp_unslash( $_SERVER['REQUEST_URI'] ), '/wp-json/' ) !== false ) {
return new WP_Error( 'rest_forbidden', 'REST API закрыт для гостей.', array( 'status' => 401 ) );
}
return $result;
} );Как проверить, что решение сработало
Проверка должна быть не только визуальной. Откройте сайт в режиме инкогнито и попробуйте запросить /wp-json/. Для гостя должен вернуться отказ или ограниченный ответ, а в админке под авторизованной сессией всё должно работать как раньше. Затем откройте редактор записи и сохраните черновик: если REST API сломан, проблемы обычно проявляются именно здесь.
- Гость не получает доступ к общему REST-индексу.
- Авторизованный пользователь может открывать и сохранять записи.
- Нет ошибок в консоли браузера на страницах с блоками и формами.
- Публичные интеграции, если они есть, продолжают отвечать.
Если вы видите 401 в браузере, но редактор работает, это нормальный результат для такой настройки. Если же редактор не сохраняет изменения или в консоли появляются ошибки fetch-запросов, значит вы закрыли лишний маршрут.
Частые ошибки и как их исправить
Сломали редактор блоков
Причина обычно в том, что блокируется весь REST API без исключений. Исправление простое: оставьте доступ авторизованным пользователям и проверьте, не режете ли вы запросы к /wp-json/wp/v2/.
Закрыли публичный маршрут, который нужен форме или плагину
Если форма отправки, поиск или фильтр перестали работать, значит вы не учли конкретный endpoint. В таком случае не держите общий запрет без списка исключений. Сначала найдите нужный маршрут, потом добавьте его в whitelist.
Проверяли без очистки кеша
Иногда кажется, что правило не работает, но на деле вы видите старый кеш страницы или ответа. После изменений очистите кеш плагина, серверный кеш и CDN, если он есть.
Добавили код в тему и потеряли его после обновления
Это типичная ошибка. Для таких правок лучше использовать mu-plugin или отдельный мини-плагин. Тогда ограничение не исчезнет при смене темы.
Практические советы по безопасности и производительности
Если цель — не только закрыть лишнее, но и уменьшить шум от ботов, не ограничивайтесь одним REST API. Посмотрите на XML-RPC, спам-формы, лишние публичные эндпоинты и тяжелые запросы в админке. Но не пытайтесь «оптимизировать» всё сразу: сначала зафиксируйте, что именно даёт нагрузку или риск.
Для сайтов с большим количеством кастомных интеграций полезно вести короткий список разрешённых маршрутов. Это дисциплинирует поддержку: когда появляется новый плагин, сразу видно, нужен ли ему публичный доступ. Такой подход обычно надёжнее, чем глобальные запреты без тестов.
Если задача шире и вам нужно не только закрыть REST API, но и убрать дубли, мусорные скрипты и лишние запросы, посмотрите в сторону инструментов для технической чистки сайта. В некоторых проектах это проще делать через набор точечных настроек, чем через десяток разрозненных сниппетов.