wpstart.ru wordpress wpstart.ru

Как закрыть публичный доступ к WP REST API в WordPress и оставить нужные запросы

WP REST API часто оставляют открытым по умолчанию, а потом удивляются лишним запросам к /wp-json/, светящимся данным о сайте и шуму в логах. Полностью отключать API обычно плохая идея: Gutenberg, админка и часть плагинов на нём завязаны. Рабочий сценарий другой — ограничить публичные маршруты, но не сломать то, что реально используется внутри сайта.

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

Когда проблема действительно в REST API

Сначала стоит убедиться, что речь не о ложной тревоге. Сам по себе /wp-json/ — не ошибка. Проблема начинается, когда:

  • в логах много запросов к REST-маршрутам от ботов и парсеров;
  • по адресу /wp-json/wp/v2/users или похожим endpoint’ам видны данные, которые вы не хотите отдавать публично;
  • внешние сервисы дергают API без авторизации и получают слишком много информации;
  • после установки плагина безопасности сайт начал отдавать 403 на запросы редактора или мобильного приложения;
  • нужно оставить API только для авторизованных пользователей или конкретных интеграций.

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

Откройте в браузере или через curl несколько адресов и посмотрите, что реально отдается:

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

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

Какие есть варианты: код, плагин или серверное правило

Для этой задачи обычно используют три подхода. У каждого есть компромисс.

ПодходЧто делаетПлюсыМинусы
Код в теме или mu-pluginФильтрует REST-маршруты на уровне WordPressТочечно, прозрачно, можно оставить нужные endpoint’ыНужно аккуратно тестировать
Плагин безопасностиДаёт готовые настройки и исключенияБыстро включить, меньше кодаНе всегда понятно, что именно он блокирует
Правило на сервереРежет доступ до WordPressСнижает нагрузку раньше PHPЛегко сломать редактор и интеграции

Если нужен контроль без лишней магии, практичнее начать с кода. Для точечной задачи это обычно предсказуемее, чем глобальные настройки безопасности.

Пошаговое решение: закрываем публичные маршруты и оставляем рабочие

Самый безопасный вариант — не отключать REST API целиком, а ограничить только публичные ответы для неавторизованных пользователей. Для этого удобно использовать фильтр rest_authentication_errors.

Вариант 1: блокировать REST API для гостей

Если сайт не использует публичные API-запросы от внешних сервисов, можно запретить доступ неавторизованным пользователям. Код лучше класть в mu-plugin или в отдельный мини-плагин, а не в functions.php активной темы.

<?php
/**
 * Plugin Name: Restrict REST API for guests
 */
add_filter( 'rest_authentication_errors', function( $result ) {
    if ( ! empty( $result ) ) {
        return $result;
    }

    if ( is_user_logged_in() ) {
        return $result;
    }

    // Разрешаем только базовый индекс API, если он нужен для диагностики.
    $uri = isset( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : '';
    if ( strpos( $uri, '/wp-json/' ) !== false ) {
        return new WP_Error(
            'rest_forbidden',
            __( 'REST API доступен только авторизованным пользователям.', 'textdomain' ),
            array( 'status' => 401 )
        );
    }

    return $result;
} );

Это грубый вариант. Он подходит, если у вас нет публичных интеграций и вы точно понимаете, что блокируете. Для обычного сайта чаще нужен более мягкий фильтр.

Вариант 2: закрыть только чувствительные маршруты

Чаще всего достаточно запретить отдельные endpoint’ы, например список пользователей. Так вы не ломаете весь API, но убираете лишнюю утечку данных.

<?php
add_filter( 'rest_endpoints', function( $endpoints ) {
    if ( isset( $endpoints['/wp/v2/users'] ) ) {
        unset( $endpoints['/wp/v2/users'] );
    }

    if ( isset( $endpoints['/wp/v2/users/(?P<id>[\d]+)'] ) ) {
        unset( $endpoints['/wp/v2/users/(?P<id>[\d]+)'] );
    }

    return $endpoints;
} );

Такой подход полезен, если вам нужно убрать именно публичный список авторов, но оставить остальной REST API для редактора, блоков и плагинов.

Вариант 3: ограничить доступ только для конкретных маршрутов

Если внешняя интеграция использует один маршрут, а остальное API не нужно, можно проверять namespace и разрешать только нужное. Это уже более точечная настройка, но и ответственность выше: надо знать, какие запросы делает сайт.

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

    $route = $request->get_route();

    // Разрешаем только публичные служебные запросы, если они нужны.
    $allowed = array(
        '/wp/v2/posts',
        '/wp/v2/pages',
    );

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

    return new WP_Error(
        'rest_forbidden',
        __( 'Этот REST-маршрут закрыт для гостей.', 'textdomain' ),
        array( 'status' => 403 )
    );
}, 10, 3 );

Этот код уже требует тестирования на конкретном сайте. Если у вас есть формы, headless-фронтенд, мобильное приложение или SEO-плагин с REST-запросами, список разрешённых маршрутов придётся расширять.

Как не сломать редактор, формы и внешние сервисы

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

  • работающий вход в админку;
  • открытие и сохранение записей в редакторе;
  • формы, которые отправляют данные через AJAX или REST;
  • внешние сервисы, если они подключены к сайту;
  • мобильные приложения или headless-фронтенд, если они есть.

Если сайт корпоративный и у него много интеграций, лучше сначала ограничить только чувствительные маршруты, а не весь API. Это снижает риск случайно отрезать нужный функционал.

Проверка результата после внедрения

После правки не ограничивайтесь одной проверкой в браузере. Нужна короткая, но практичная валидация.

  1. Откройте /wp-json/ в браузере в режиме гостя и убедитесь, что поведение соответствует выбранной схеме.
  2. Проверьте /wp-json/wp/v2/users — он не должен отдавать лишние данные публично, если вы его закрывали.
  3. Зайдите в админку и откройте редактор записи.
  4. Сохраните запись и проверьте, что автосохранение не сломалось.
  5. Если есть формы, отправьте тестовую заявку.
  6. Посмотрите error log и консоль браузера на предмет 401/403 и JS-ошибок.

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

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

Если вы закрывали маршрут для гостей, ожидаемым результатом будет 401 или 403, а не полноценный JSON-ответ.

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

Сломали редактор после полного отключения API

Причина обычно в слишком грубом фильтре или серверном правиле, которое режет все запросы к /wp-json/. Исправление простое: верните базовый REST API и блокируйте только конкретные маршруты или неавторизованных гостей через WordPress-фильтры.

Отключили не тот endpoint

Иногда убирают маршруты, которые использует плагин SEO, формы или блоки. В этом случае сначала включите логирование запросов, потом посмотрите, какой маршрут реально нужен, и добавьте его в исключения.

Проверяли только в админке

Админка может работать, а публичная часть уже ловит ошибки. Обязательно тестируйте и фронтенд, и формы, и кэш, если он стоит на сайте.

Сделали правку в теме, а потом обновили её

Если код лежит в functions.php, он может исчезнуть после обновления. Для таких задач лучше использовать mu-plugin или отдельный мини-плагин.

Что делать, если нужен более мягкий вариант

Иногда не нужно закрывать API полностью. Достаточно убрать только публичные сведения и оставить служебные маршруты. В таком случае полезно сочетать ограничение REST API с чисткой лишних публичных endpoint’ов, отключением ненужных архивов и контролем индексации. Если у вас уже есть плагин для технической чистки сайта, например Clearfy Pro, часть подобных настроек можно собрать в одном месте, но всё равно стоит понимать, что именно он меняет.

Если задача касается не только REST API, а ещё и индексации дублей, служебных страниц и мусорных endpoint’ов, сначала составьте список того, что реально используется сайтом. Это дешевле, чем потом искать, почему редактор перестал сохранять блоки или внешняя интеграция начала получать 403.

В итоге рабочая схема выглядит так: сначала находите, какие маршруты действительно используются, потом ограничиваете только лишнее, после этого проверяете редактор, формы и публичный фронтенд. Для WordPress это почти всегда надёжнее, чем «выключить всё и посмотреть, что сломалось».

×

AI-плагин от WPShop.ru

анализирует конкурентов

пишет статьи

готовит SEO

генерирует изображения

и еще кое-что...
WPGPT
Плагин, который наполняет ваш сайт WordPress
Узнать больше