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

Если вам нужно закрыть REST API WordPress для гостей, не стоит рубить его целиком. На практике это часто ломает блоки редактора, AJAX-запросы темы, формы, поиск, мобильные приложения и плагины, которые обращаются к эндпоинтам без входа в админку. Безопаснее не отключать API полностью, а ограничить доступ только для неавторизованных пользователей и при этом оставить те запросы, которые действительно нужны сайту.

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

Что именно мы ограничиваем

REST API в WordPress доступен по адресу вида /wp-json/. Через него работают как внутренние запросы самого WordPress, так и обращения плагинов, темы, внешних сервисов и фронтенд-скриптов. Полное отключение API обычно плохая идея: WordPress и экосистема давно рассчитывают на его наличие.

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

Безопасный способ: ограничить REST API через functions.php или мини-плагин

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

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

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

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_prefixes = array(
        '/wp-json/wp/v2/',
        '/wp-json/oembed/1.0/',
        '/wp-json/wp-site-health/',
    );

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

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

Что делает этот код:

  • не трогает уже обработанные ошибки и ответы других плагинов;
  • разрешает доступ авторизованным пользователям;
  • для гостей пропускает только выбранные маршруты;
  • для всего остального возвращает 403 Forbidden.

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

Как оставить только нужные запросы

Самая частая ошибка — закрыть API целиком и потом искать, почему перестали работать блоки редактора, превью, комментарии, формы или поиск. Поэтому сначала проверьте, какие запросы реально нужны вашему сайту.

Практически это делается так:

  1. Откройте сайт в браузере в режиме гостя.
  2. Откройте инструменты разработчика и вкладку Network.
  3. Обновите страницу и посмотрите, какие запросы идут на /wp-json/.
  4. Отдельно проверьте страницы с формами, блоками, фильтрами, поиском и любыми интерактивными элементами.

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

Если вы знаете конкретный маршрут, который должен работать для гостей, добавьте его в массив $allowed_prefixes. Например, если плагин использует собственный префикс /wp-json/my-plugin/v1/, его можно разрешить отдельно:

$allowed_prefixes = array(
    '/wp-json/wp/v2/',
    '/wp-json/oembed/1.0/',
    '/wp-json/wp-site-health/',
    '/wp-json/my-plugin/v1/',
);

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

Когда лучше не использовать код в теме

Если вы не хотите зависеть от темы, создайте маленький mu-plugin. Это особенно удобно, если на сайте несколько администраторов или тема может меняться. Mu-plugin загружается автоматически и не отключается случайно из админки.

Для этого создайте файл, например wp-content/mu-plugins/limit-rest-api.php. Если папки mu-plugins нет, её нужно создать вручную. Внутрь поместите тот же код, только оберните его в стандартный PHP-файл:

<?php
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_prefixes = array(
        '/wp-json/wp/v2/',
        '/wp-json/oembed/1.0/',
        '/wp-json/wp-site-health/',
    );

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

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

Этот вариант удобнее для поддержки: код не потеряется при смене темы и не зависит от шаблона сайта.

Как проверить, что сайт не сломался

После включения ограничения проверьте не только главную страницу, но и те разделы, которые чаще всего используют REST API.

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

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

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

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

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

Итог простой: не отключайте REST API в WordPress «в ноль». Закрывайте только лишнее, оставляйте нужные маршруты и обязательно проверяйте сайт после изменений. Тогда вы получите и меньше лишнего трафика к API, и меньше шансов сломать тему или плагины.

⭐⭐⭐⭐⭐