wptavern.ru wordpress wptavern.ru

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

Полностью отключать WP REST API на живом сайте — плохая идея, если вы не проверили, кто именно его использует. На практике проблема обычно выглядит так: в логах много запросов к /wp-json/, сторонние скрипты дергают публичные эндпоинты, а админка и редактор Gutenberg продолжают работать через REST. Нужен не «рубильник», а точечное ограничение.

Ниже — рабочий сценарий: сначала диагностика, потом выбор подхода, затем проверка, что редактор, формы, SEO-плагины и интеграции не отвалились.

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

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

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

Если у вас работает мобильное приложение, фронтенд на React/Vue или интеграция с CRM, сначала проверьте, какие маршруты реально используются. Иначе можно сломать публикацию записей, автосохранение, медиа-загрузку или формы, которые отправляют данные через REST.

Диагностика: что именно использует REST API

Перед изменениями посмотрите, какие запросы идут на сайт. Самый простой способ — открыть DevTools в браузере и отфильтровать запросы по wp-json. Если запросы идут из админки, это нормально. Если они приходят с публичной части сайта без явной причины, это уже повод разбираться.

Проверка в логах сервера

В access.log ищите обращения к /wp-json/. Если видите частые запросы к одним и тем же маршрутам, проверьте, какой плагин или скрипт их вызывает. Для Nginx это обычно делается обычным grep по логам:

grep -R "wp-json" /var/log/nginx/access.log*

На Apache логика та же: ищем URL, затем сопоставляем время запроса с действиями на сайте. Это не даст готового ответа, но быстро покажет, есть ли у REST реальная нагрузка или это просто редкие обращения.

Что нельзя отключать без проверки

Не трогайте REST API вслепую, если на сайте есть:

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

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

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

Самый безопасный вариант — разрешить REST только авторизованным пользователям, а анонимным вернуть ошибку для большинства маршрутов. Это не ломает работу редактора для вошедших в систему и не мешает админке.

Вариант через rest_authentication_errors

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

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

    foreach ( $allowed_prefixes as $prefix ) {
        if ( str_starts_with( $uri, $prefix ) ) {
            return $result;
        }
    }

    return new WP_Error(
        'rest_forbidden',
        __( 'REST API доступен только авторизованным пользователям.', 'textdomain' ),
        array( 'status' => 401 )
    );
} );

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

Блокировка только списка пользователей

Частая задача — скрыть пользователей от анонимных запросов, но не ломать остальной API. Для этого можно перехватить маршрут /wp/v2/users:

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

    foreach ( $endpoints['/wp/v2/users'] as $index => $handler ) {
        if ( isset( $handler['permission_callback'] ) ) {
            $endpoints['/wp/v2/users'][ $index ]['permission_callback'] = function() {
                return current_user_can( 'list_users' );
            };
        }
    }

    return $endpoints;
} );

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

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

ПодходЧто делаетПлюсыМинусы
ПлагинОтключает или ограничивает REST через настройкиБыстро, без кодаНе всегда прозрачно, может конфликтовать с другими плагинами
Код через rest_authentication_errorsОграничивает доступ на уровне WordPressГибко, можно оставить исключенияНужно тестировать совместимость
Правило на сервереБлокирует URL до загрузки WordPressСнижает нагрузкуЛегко сломать админку и служебные запросы, если правило слишком широкое

Если цель — именно безопасность и контроль, код в WordPress обычно безопаснее, чем грубая блокировка на уровне Nginx/Apache. Серверное правило имеет смысл только когда вы точно знаете, какие маршруты можно отрезать.

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

После изменения не ограничивайтесь открытием главной страницы. Проверьте несколько сценариев отдельно.

  • Откройте /wp-json/ в режиме инкогнито: должен вернуться отказ или ограниченный ответ, если вы так настроили.
  • Зайдите в админку и откройте редактор записи: автосохранение и загрузка блоков должны работать.
  • Проверьте медиа-библиотеку и загрузку изображений.
  • Если есть формы, отправьте тестовую заявку и посмотрите, не используют ли они REST.
  • Проверьте интеграции плагинов, которые синхронизируют данные с внешними сервисами.

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

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

Сломали Gutenberg

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

Перестали работать формы или интеграции

Некоторые плагины отправляют данные через REST, а не через admin-ajax.php. Если после ограничения форма перестала отправляться, откройте сетевые запросы и посмотрите, какой маршрут используется. Затем добавьте точечное исключение для этого эндпоинта.

Серверное правило блокирует лишнее

Если вы закрывали /wp-json/ через Nginx или .htaccess, легко задеть oEmbed, API плагинов и служебные вызовы. В таком случае лучше убрать жесткую блокировку и перенести логику в WordPress-фильтр, где можно проверять пользователя и маршрут.

Появились ошибки в консоли браузера

Это обычно признак того, что фронтенд или плагин ожидает JSON-ответ, а получил HTML-страницу ошибки или редирект. Откройте DevTools, найдите запрос с ошибкой и проверьте, какой именно endpoint отвалился.

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

Если цель — не только ограничить доступ, но и снизить шум, не забывайте про базовые вещи:

  • обновляйте ядро, плагины и тему, чтобы не держать старые уязвимости;
  • не оставляйте открытыми лишние публичные маршруты, если они не нужны;
  • проверяйте, не дублируют ли плагины друг друга одну и ту же функцию;
  • не блокируйте REST ради «ускорения», если сайт реально его использует — выигрыш от такого шага часто мнимый;
  • если нужен более широкий аудит дублей, мета-данных и служебных настроек, удобнее сначала почистить сайт, а не резать API наугад.

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

Мини-чек-лист перед публикацией изменений

  • Поняли, какие плагины и сценарии используют REST.
  • Выбрали точечное ограничение, а не полный запрет.
  • Проверили вход в админку и работу Gutenberg.
  • Протестировали формы, медиа и интеграции.
  • Посмотрели HTTP-коды и ошибки в консоли.
  • Сохранили код в mu-plugin или дочерней теме, а не в случайном месте.

Если после внедрения сайт работает как раньше, но публичные запросы к ненужным маршрутам больше не проходят, задача решена. Если что-то отвалилось — откатывайте правило и сужайте его до конкретного endpoint, а не до всего /wp-json/.

×
до 3225₽

Продавай темы и плагины WordPress!

Лови с каждой продажи

Начать ⋙