Как ограничить REST API в WordPress для неавторизованных запросов

REST API в WordPress часто оставляют открытым по умолчанию, а потом удивляются лишним запросам, шуму в логах и лишней нагрузке. Полностью отключать API обычно плохая идея: Gutenberg, некоторые формы, мобильные приложения и внешние сервисы могут перестать работать. Рабочий подход — ограничить доступ для неавторизованных запросов и оставить нужные эндпоинты только там, где они реально используются.

Когда ограничение REST API действительно нужно

Типичный сценарий: сайт не использует публичный API, но в логах видны запросы к /wp-json/, а в отчётах по безопасности всплывают перечисления пользователей через /wp-json/wp/v2/users. Ещё один частый случай — API нужен только для админки и редактора, а внешним клиентам доступ не требуется. В такой конфигурации имеет смысл закрыть большую часть маршрутов для гостей и оставить исключения точечно.

Что именно стоит проверить до изменений

  • Используется ли Gutenberg в админке и нет ли ошибок при открытии записей.
  • Есть ли формы, которые отправляют данные через REST API.
  • Подключены ли мобильные приложения, headless-фронтенд или внешние интеграции.
  • Не завязаны ли плагины на публичные маршруты wp-json.

Диагностика проблемы: какие запросы открыты сейчас

Перед правками полезно понять, какие маршруты доступны без авторизации. Самый простой способ — открыть главную страницу сайта и проверить ответ на /wp-json/. Если сервер возвращает JSON со списком маршрутов, это нормально. Вопрос в том, какие из них доступны гостям и не несут ли лишнюю информацию.

Для быстрой проверки можно использовать curl:

curl -I https://example.com/wp-json/wp/v2/users

Если маршрут отдаёт 200 OK без авторизации, это уже повод ограничить доступ. Если возвращается 401 или 403, значит защита уже работает на уровне ядра, плагина или сервера.

Ещё полезно проверить, не ломается ли редактор после ограничений. Именно здесь многие делают ошибку: закрывают весь REST API, а потом получают проблемы в админке, потому что Gutenberg и связанные компоненты не могут получать данные.

Как ограничить REST API кодом без отключения редактора

Самый предсказуемый вариант — добавить фильтр rest_authentication_errors в мини-плагин или в functions.php дочерней темы. Логика простая: если пользователь не авторизован, блокируем доступ ко всем маршрутам, кроме тех, которые вы явно разрешили.

<?php
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/',
    );

    // Разрешаем только конкретные маршруты, если они нужны гостям.
    $allowed_routes = array(
        '/wp-json/wp/v2/posts',
        '/wp-json/wp/v2/pages',
    );

    foreach ( $allowed_routes as $route ) {
        if ( strpos( $uri, $route ) === 0 ) {
            return $result;
        }
    }

    if ( strpos( $uri, '/wp-json/' ) === 0 ) {
        return new WP_Error(
            'rest_forbidden',
            __( 'REST API доступен только авторизованным пользователям.', 'textdomain' ),
            array( 'status' => 401 )
        );
    }

    return $result;
} );

Этот пример намеренно простой. На практике лучше не полагаться на REQUEST_URI для сложной логики, если у вас много исключений. Но для типового сайта, где нужно закрыть публичные запросы и оставить только несколько маршрутов, решение работает предсказуемо.

Если нужен более точный контроль по маршрутам

Когда API используют отдельные плагины или внешние сервисы, удобнее проверять сам запрос через объект WP_REST_Request. Для этого можно перехватывать конкретные маршруты через rest_pre_dispatch и разрешать только нужные эндпоинты. Такой подход аккуратнее, но требует тестирования на реальных сценариях.

<?php
add_filter( 'rest_pre_dispatch', function( $result, $server, $request ) {
    if ( is_user_logged_in() ) {
        return $result;
    }

    $route = $request->get_route();

    $public_routes = array(
        '/wp/v2/posts',
        '/wp/v2/pages',
    );

    if ( in_array( $route, $public_routes, true ) ) {
        return $result;
    }

    return new WP_Error(
        'rest_forbidden',
        __( 'Доступ к этому REST-методу ограничен.', 'textdomain' ),
        array( 'status' => 401 )
    );
}, 10, 3 );

Здесь важно понимать: если вы ограничиваете маршруты слишком агрессивно, часть плагинов может начать падать не сразу, а только при выполнении конкретного действия. Поэтому после внедрения нужно пройтись по админке и по всем формам, которые есть на сайте.

Сравнение подходов: плагин, код или серверная блокировка

ПодходКогда подходитПлюсыМинусы
Плагин безопасностиНужна быстрая настройка без кодаПроще включить и откатитьМожет давать слишком общие правила
Код в теме или мини-плагинеНужны точные исключенияГибкий контроль маршрутовТребует тестирования и поддержки
Серверная блокировкаНужно резать трафик до PHPМеньше нагрузки на WordPressСложнее не сломать легитимные запросы

Если задача только в том, чтобы убрать лишний шум и закрыть публичные пользовательские маршруты, кодовый вариант обычно удобнее. Если нужен жёсткий контроль на уровне Nginx или Apache, это уже отдельная история и там нужно учитывать конфигурацию хоста.

Пошаговая настройка без лишнего риска

  1. Сделайте резервную копию файлов и базы.
  2. Проверьте, какие плагины и функции используют REST API.
  3. Добавьте ограничение в мини-плагин, а не прямо в родительскую тему.
  4. Оставьте исключения для нужных публичных маршрутов.
  5. Проверьте вход в админку, Gutenberg, формы и интеграции.
  6. Посмотрите логи сервера и ответы 401/403 на закрытые маршруты.

Мини-плагин здесь удобнее, чем правка functions.php: его проще отключить, если что-то пойдёт не так. Для рабочих сайтов это практичнее, чем вносить правки в тему и потом ловить проблему после обновления.

Как проверить, что ограничение сработало

Проверка должна быть не только технической, но и прикладной. Сначала убедитесь, что закрытые маршруты действительно перестали отвечать гостям. Затем проверьте, что авторизованный пользователь по-прежнему может работать с админкой и редактором.

  • Откройте /wp-json/wp/v2/users в режиме инкогнито.
  • Проверьте /wp-json/wp/v2/posts и другие разрешённые маршруты.
  • Создайте или отредактируйте запись в Gutenberg.
  • Отправьте форму, если она использует REST-запросы.
  • Посмотрите, нет ли новых ошибок в debug.log или логах веб-сервера.

Если сайт использует кэш или CDN, не забудьте очистить их после изменений. Иначе можно проверить старую версию ответа и сделать неверный вывод, что защита не сработала.

Частые ошибки и как их исправить

Полностью закрыли весь REST API

Это самая частая ошибка. После такой правки редактор может начать вести себя нестабильно, а некоторые плагины — перестать сохранять данные. Исправление простое: не блокируйте всё подряд, а оставьте разрешённые маршруты для нужных сценариев.

Проверяют только главную страницу, а не конкретные маршруты

То, что /wp-json/ открывается, ещё не означает, что всё плохо. Важно смотреть конкретные эндпоинты, особенно users, пользовательские маршруты плагинов и публичные методы, которые отдают чувствительные данные.

Вносят правки в родительскую тему

После обновления темы ограничение исчезает. Для таких задач лучше использовать мини-плагин или mu-plugin. Это надёжнее и не зависит от дизайна сайта.

Не тестируют авторизованные сценарии

Ограничение может быть безопасным для гостей, но ломать сохранение записей или интеграцию с формой. Поэтому проверка должна идти от реального сценария, а не только от ответа 401 в браузере.

Практические советы по безопасности и производительности

Если цель — уменьшить поверхность атаки, одного REST API обычно недостаточно. Имеет смысл одновременно проверить XML-RPC, список пользователей, индексацию технических страниц и лишние публичные маршруты плагинов. Но не стоит отключать всё подряд без анализа: иногда именно публичный маршрут нужен для нормальной работы сайта.

Для сайтов, где важна техническая чистота, полезно держать под рукой инструменты, которые помогают убирать дубли и лишние служебные элементы. Например, Clearfy Pro уместен там, где нужно последовательно навести порядок в SEO, дублях и технических настройках без ручной правки каждого шаблона. Если же вы работаете через код, всё равно сначала проверяйте, что именно использует API, а уже потом режьте доступ.

И ещё один практический момент: если вы закрываете REST API на уровне PHP, не забывайте про нагрузку. Чем раньше запрос будет отклонён, тем лучше. Но если правила слишком сложные и выполняются на каждом обращении, выигрыш может оказаться меньше ожидаемого.

Оптимизация базы данных WordPress для ускорения сайта
17.11.2025
Автоматизация обновления тем и удаление старых ревизий в WordPress
21.03.2026
Как защитить WordPress от слишком большого количества попыток входа
02.12.2025
Как использовать WPRemark для автоматического управления отзывами в WordPress
10.02.2026
Автоматическое удаление возвращённых и отменённых заказов WooCommerce
05.07.2026