REST API в WordPress часто оставляют открытым по умолчанию, а потом удивляются лишним запросам, светящимся в логах и доступности служебных данных для незалогиненных посетителей. Полностью выключать REST API обычно плохая идея: редактор блоков, многие плагины и часть фронтенд-функций завязаны на него. Рабочий сценарий — ограничить доступ для гостей точечно, не трогая нужные эндпоинты.
Когда это действительно проблема
Сначала стоит понять, что именно вы хотите закрыть. Если в логах видно много запросов к /wp-json/, это не всегда атака. Иногда это обычный сканер, иногда — тема или плагин, который дергает API на фронтенде. Проблема начинается, когда:
- гостям доступны данные, которые не должны индексироваться или светиться публично;
- на сайте есть лишняя нагрузка от массовых запросов к REST API;
- плагин безопасности уже начал блокировать запросы, а вы не понимаете, что именно ломается;
- нужно закрыть API для анонимных пользователей, но оставить работу админки и авторизованных запросов.
Что проверить до изменений
Откройте несколько типичных URL и посмотрите, что возвращается:
/wp-json/— базовый индекс API;/wp-json/wp/v2/posts— публичные записи;/wp-json/wp/v2/users— список пользователей, если он доступен;- запросы плагинов, если они используют собственные маршруты.
Если у вас включен кэш, проверьте еще и заголовки ответа. Иногда кажется, что REST API «закрыт», но на деле отдает закэшированный JSON через CDN или reverse proxy.
Какой способ выбрать: плагин, код или частичная блокировка
Универсального переключателя «выключить REST API только для гостей» в ядре нет. Поэтому обычно используют либо код в functions.php дочерней темы, либо мини-плагин, либо правила на уровне веб-сервера. Для большинства сайтов самый предсказуемый вариант — код с белым списком маршрутов.
| Подход | Плюсы | Минусы |
|---|---|---|
| Код в теме или mu-plugin | Точечный контроль, легко проверить | Нужно аккуратно поддерживать список разрешений |
| Плагин безопасности | Быстро включить без разработки | Может блокировать лишнее или конфликтовать с другими плагинами |
| Блокировка на сервере | Снижает нагрузку раньше PHP | Сложнее не задеть нужные маршруты и авторизованные запросы |
Если задача не только в безопасности, но и в чистке сайта от лишних публичных точек входа, имеет смысл сначала посмотреть, какие маршруты реально используются. Для этого удобно временно включить логирование запросов или проверить обращения в access.log.
Пошаговое решение: закрываем REST API для гостей
Ниже вариант, который блокирует REST-запросы для незалогиненных пользователей, но оставляет доступ к выбранным маршрутам. Его лучше размещать в мини-плагине или mu-plugin, а не в активной теме, чтобы правило не пропало при смене дизайна.
<?php
/**
* Plugin Name: Restrict REST API for guests
*/
add_filter( 'rest_authentication_errors', function ( $result ) {
if ( true === $result || is_wp_error( $result ) ) {
return $result;
}
if ( is_user_logged_in() ) {
return $result;
}
$request_uri = isset( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : '';
// Разрешаем только нужные маршруты. Список подстройте под свой сайт.
$allowed_paths = array(
'/wp-json/',
'/wp-json/wp/v2/posts',
'/wp-json/wp/v2/pages',
);
foreach ( $allowed_paths as $allowed_path ) {
if ( str_starts_with( $request_uri, $allowed_path ) ) {
return $result;
}
}
return new WP_Error(
'rest_forbidden',
__( 'REST API доступен только авторизованным пользователям.', 'textdomain' ),
array( 'status' => 403 )
);
} );Этот вариант не идеален для всех случаев, потому что часть плагинов может использовать собственные маршруты, а фронтенд — запросы к публичным данным. Поэтому после внедрения важно не просто открыть главную страницу, а пройтись по реальным сценариям: поиск, формы, блоки, комментарии, личный кабинет, если он есть.
Если нужно закрыть только список пользователей
Частая задача — убрать публичный доступ к /wp-json/wp/v2/users, но оставить остальное. Тогда лучше не рубить весь API, а ограничить конкретный маршрут:
<?php
add_filter( 'rest_endpoints', function ( $endpoints ) {
if ( ! isset( $endpoints['/wp/v2/users'] ) ) {
return $endpoints;
}
if ( ! is_user_logged_in() ) {
unset( $endpoints['/wp/v2/users'] );
}
return $endpoints;
} );Это более мягкий сценарий, но он не заменяет полноценную проверку. Если какой-то плагин ожидает доступ к users endpoint для авторизованного пользователя, убедитесь, что вы не мешаете его работе.
Проверка результата после внедрения
После изменений не ограничивайтесь ручным просмотром главной страницы. Проверьте несколько точек:
- откройте
/wp-json/в режиме гостя и убедитесь, что видите только разрешенные данные или ошибку 403; - проверьте
/wp-json/wp/v2/users— он должен быть недоступен для анонимного запроса, если вы его закрывали; - авторизуйтесь в админке и повторите те же запросы: для администратора или редактора они должны работать, если это предусмотрено логикой сайта;
- посмотрите консоль браузера и Network: нет ли ошибок на фронтенде после блокировки;
- проверьте логи сервера на повторяющиеся 403 от нужных плагинов или тем.
Если есть доступ к WP-CLI, можно быстро проверить, не сломалась ли структура сайта и не появились ли фатальные ошибки после правки:
wp plugin list
wp theme list
wp cron event listЭти команды не тестируют REST API напрямую, но помогают убедиться, что сайт в целом живой и нет побочных проблем после изменения кода.
Частые ошибки и как их исправить
Закрыли весь REST API и сломали редактор
Это самая типичная ошибка. Gutenberg и часть административных сценариев используют REST API для сохранения и загрузки данных. Если вы блокируете запросы без исключений для авторизованных пользователей, редактор начнет сбоить. Исправление простое: не блокируйте API глобально, а проверяйте is_user_logged_in() и разрешайте нужные маршруты.
Положились на URL-строку и забыли о прокси
Сравнение REQUEST_URI работает в большинстве обычных установок, но при нестандартных прокси, поддоменах или переписанных маршрутах лучше дополнительно смотреть на реальные REST-запросы через rest_authentication_errors. Если у вас сложная инфраструктура, тестируйте не только в браузере, но и через curl.
Не учли плагины, которые используют собственные маршруты
Плагины форм, поиска, кеша, мультиязычности и подписок нередко обращаются к собственным REST-маршрутам. После блокировки они могут начать молча деградировать: кнопки перестанут работать, а ошибок в интерфейсе не будет. В таком случае добавьте нужный маршрут в белый список или ограничьте только проблемный endpoint.
Проверили только главную страницу
Это плохая привычка. REST API часто используется не на главной, а в архиве записей, в блоках с динамическим контентом, в формах и в личном кабинете. После внедрения обязательно пройдитесь по всем ключевым шаблонам.
Практические советы по безопасности и производительности
Если цель — не просто «спрятать» API, а реально снизить риски, держите в голове несколько вещей:
- не отключайте REST API ради косметики, если сайт активно использует блоки и современные плагины;
- не храните список разрешений в случайном сниппете без комментария — через месяц будет сложно понять, зачем он нужен;
- если блокируете API на уровне сервера, сначала протестируйте на staging;
- следите за кэшем: иногда 403 или старый JSON остаются в CDN и создают ложное ощущение, что правило не работает;
- для сайтов с повышенными требованиями к чистке и SEO полезно отдельно проверить, не светятся ли через API лишние данные, которые потом попадают в индекс.
Если вам нужно не только ограничить REST API, но и убрать другие технические дубли и служебные точки входа, имеет смысл смотреть на комплексную чистку сайта. В таких задачах часто удобнее сначала определить, что именно мешает, а уже потом резать доступ точечно, а не «на всякий случай».
В итоге рабочая схема выглядит так: сначала находите реальные маршруты, потом ограничиваете только лишнее, затем проверяете фронтенд, админку и логи. Это дольше, чем поставить грубый запрет, но именно так WordPress остается рабочим, а не просто «закрытым».