REST API в WordPress часто оставляют открытым «по умолчанию», а потом удивляются лишним запросам, утечке данных о пользователях или нагрузке на сервер. Полностью отключать его обычно плохая идея: редактор Gutenberg, некоторые плагины и внешние интеграции могут перестать работать. Гораздо полезнее ограничить доступ точечно — оставить нужное и убрать лишнее.
Ниже разберём рабочий сценарий: как понять, что именно у вас лишнее, как закрыть REST API для незалогиненных пользователей, какие эндпоинты лучше не трогать и как проверить, что после изменений сайт не получил новые ошибки.
Когда REST API становится проблемой
Сам по себе REST API не «вредный». Проблемы начинаются, когда сайт:
- отдаёт слишком много данных о пользователях и записях;
- получает много запросов к
/wp-json/от ботов; - использует плагины, которым REST API не нужен, но он всё равно открыт;
- имеет публичные авторские страницы, а в API видны логины и ID пользователей;
- работает на слабом хостинге, где лишние запросы заметно нагружают PHP.
Если у вас уже есть жалобы на медленную админку, странные обращения к /wp-json/wp/v2/users или рост 4xx/5xx в логах, сначала посмотрите, какие именно маршруты вызываются чаще всего. Не стоит сразу ставить жёсткий запрет на весь API.
Диагностика: что именно нужно ограничить
Перед правкой кода проверьте три вещи.
1. Какие запросы идут в логи
Если есть доступ к access log, найдите обращения к /wp-json/. На типовом сайте часто всплывают:
/wp-json/wp/v2/posts;/wp-json/wp/v2/pages;/wp-json/wp/v2/users;/wp-json/oembed/1.0/embed.
Не все из них надо блокировать. Например, oEmbed и запросы редактора могут быть нужны теме и плагинам.
2. Используется ли Gutenberg и внешние интеграции
Если сайт редактируется через блоковый редактор, REST API нужен. Если подключены формы, мобильное приложение, headless-часть или сторонний сервис синхронизации, блокировать всё подряд нельзя. В такой ситуации лучше ограничить только публичные маршруты, которые не должны быть доступны анонимно.
3. Есть ли утечка пользователей
Проверьте в браузере или через curl, что отдаёт маршрут пользователей:
curl -I https://example.com/wp-json/wp/v2/usersЕсли маршрут доступен без авторизации и возвращает список пользователей или метаданные, это уже повод для точечной защиты.
Что лучше: плагин, код или серверное правило
Для ограничения REST API есть три подхода. У каждого свой компромисс.
| Подход | Плюсы | Минусы | Когда выбирать |
|---|---|---|---|
| Плагин | Быстро включить, не нужен код | Может закрыть лишнее, сложнее контролировать исключения | Если нужно быстро убрать публичный доступ без доработки темы |
Код в functions.php или mu-plugin | Точечный контроль, можно оставить нужные маршруты | Нужно тестировать вручную | Если нужен предсказуемый результат и минимальный оверхед |
| Серверное правило | Снимает часть нагрузки до PHP | Труднее не сломать легитимные запросы | Если есть опыт работы с nginx/apache и понятен список исключений |
Для большинства сайтов разумнее начать с кода: он прозрачнее и проще откатывается.
Пошаговое решение: ограничиваем REST API для гостей
Ниже пример для mu-plugin. Это удобнее, чем править тему: код не потеряется при обновлении.
<?php
/**
* Plugin Name: WPGuest REST API Restrictor
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
add_filter( 'rest_authentication_errors', function ( $result ) {
if ( ! empty( $result ) ) {
return $result;
}
// Админке и авторизованным пользователям не мешаем.
if ( is_user_logged_in() ) {
return $result;
}
$uri = isset( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : '';
// Оставляем базовые маршруты, если они нужны теме или плагинам.
$allowed_prefixes = array(
'/wp-json/',
);
// Блокируем только чувствительные маршруты для гостей.
$blocked_patterns = array(
'#^/wp-json/wp/v2/users#',
'#^/wp-json/wp/v2/comments#',
);
foreach ( $blocked_patterns as $pattern ) {
if ( preg_match( $pattern, $uri ) ) {
return new WP_Error(
'rest_forbidden',
__( 'REST API недоступен для гостей.', 'wpguest' ),
array( 'status' => 403 )
);
}
}
return $result;
} );Этот вариант не отключает весь API, а закрывает только маршруты пользователей и комментариев для незалогиненных посетителей. Если у вас есть другие чувствительные endpoints, добавьте их в $blocked_patterns.
Если нужно закрыть весь REST API для гостей
Такой вариант стоит использовать только если вы точно знаете, что сайт не зависит от публичных REST-запросов. Код ниже жёстче:
<?php
add_filter( 'rest_authentication_errors', function ( $result ) {
if ( ! empty( $result ) ) {
return $result;
}
if ( ! is_user_logged_in() ) {
return new WP_Error(
'rest_disabled',
__( 'REST API доступен только авторизованным пользователям.', 'wpguest' ),
array( 'status' => 403 )
);
}
return $result;
} );С этим вариантом нужно быть аккуратнее: он может сломать фронтенд-скрипты, интеграции и часть плагинов. Если после включения сайт начал сыпать ошибками, откатывайте изменения и переходите к точечной блокировке.
Как не сломать Gutenberg и плагины
Самая частая ошибка — закрыть REST API целиком и потом искать, почему редактор не подгружает данные или формы перестали отправлять запросы. Чтобы этого избежать, придерживайтесь простого правила: сначала блокируйте только то, что точно не нужно гостям, а не весь механизм.
- не трогайте маршруты, которые использует редактор;
- проверьте, не обращается ли тема к
/wp-json/через JavaScript; - если есть плагин кеширования или оптимизации, очистите кеш после правки;
- проверяйте сайт в режиме инкогнито и под обычным пользователем.
Если нужен более мягкий вариант, можно не блокировать запросы, а скрыть часть данных. Например, убрать публичную выдачу пользователей через REST, но оставить остальные маршруты.
Проверка результата после внедрения
После изменений не ограничивайтесь открытием главной страницы. Проверьте несколько сценариев.
Что проверить вручную
- открывается ли админка и работает ли редактор записей;
- не сломались ли формы, которые отправляют данные через AJAX;
- не появились ли ошибки 403 в консоли браузера;
- не изменился ли вывод блоков, которые подгружают данные асинхронно.
Что проверить через браузер и curl
Для гостя маршрут пользователей должен быть закрыт:
curl -I https://example.com/wp-json/wp/v2/usersОжидаемый результат — 403 Forbidden или другой контролируемый ответ, который вы задали в коде. При этом обычные страницы сайта и админка должны работать как раньше.
Если вы ограничивали только отдельные маршруты, проверьте и разрешённые адреса. Например, базовый REST-эндпоинт или маршруты, которые использует тема.
Частые ошибки и как их исправить
Ошибка 1. Код добавили в тему, а потом потеряли после обновления
Решение простое: переносите такой код в mu-plugin или отдельный мини-плагин. Это надёжнее, чем править functions.php активной темы.
Ошибка 2. Сайт начал отдавать 403 в редакторе
Значит, вы закрыли слишком много. Вернитесь к точечной блокировке и проверьте, какие маршруты реально нужны Gutenberg и установленным плагинам.
Ошибка 3. После правки ничего не изменилось
Часто причина в кеше: серверный, плагина или CDN. Очистите все уровни кеширования и повторите проверку в приватном окне.
Ошибка 4. Блокировка завязана на REQUEST_URI, но маршрут не совпадает
Иногда прокси или нестандартная конфигурация меняют путь запроса. В таком случае лучше тестировать конкретные маршруты через rest_endpoints или проверять, какие URL реально приходят в логах.
Практические советы по безопасности и производительности
Если цель — не только закрыть лишнее, но и снизить нагрузку, не ограничивайтесь REST API. Посмотрите на соседние точки риска:
- отключите ненужные публичные авторские архивы, если они дублируют контент;
- проверьте, не отдаёт ли сайт лишние данные в XML sitemap;
- уберите неиспользуемые плагины, которые сами делают REST-запросы;
- сократите количество внешних скриптов, которые обращаются к API на каждой странице.
Если нужен более широкий набор технических чисток, удобно держать под рукой инструменты вроде Clearfy Pro: он помогает закрывать дубли, отключать лишние элементы и наводить порядок в технической части сайта. Но даже с плагином полезно понимать, что именно вы отключаете и зачем.
Главная идея здесь простая: REST API не надо ломать целиком, если проблема только в нескольких публичных маршрутах. Точечное ограничение обычно безопаснее, чем грубое отключение, и его проще сопровождать после обновлений WordPress и плагинов.