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

Публичный REST API в WordPress часто нужен для Gutenberg, мобильных приложений, интеграций и некоторых плагинов. Но на обычном сайте он же может быть лишним источником лишних запросов, утечек служебных данных и шума в логах. Если задача не в том, чтобы «выключить всё», а в том, чтобы закрыть доступ для неавторизованных запросов, это лучше делать точечно.

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

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

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

Что обычно видно в диагностике

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

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

Диагностика: что именно доступно сейчас

Перед изменениями проверьте базовые точки. Это занимает пару минут и помогает не ломать то, что уже работает.

https://example.com/wp-json/

Если в ответе виден список маршрутов, это нормально. Дальше смотрим, что доступно без авторизации. Например, такие запросы часто возвращают данные публично:

https://example.com/wp-json/wp/v2/posts?per_page=1
https://example.com/wp-json/wp/v2/pages?per_page=1

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

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

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

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

Вариант через functions.php или мини-плагин

Лучше не вносить это в тему, если сайт живёт на готовой теме и вы не хотите терять правку при обновлении. Надёжнее — маленький must-use плагин или обычный плагин для технических настроек.

<?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;
    }

    // Разрешаем только запросы из админки, если они уже авторизованы cookie/nonce.
    // Для гостей возвращаем ошибку доступа.
    return new WP_Error(
        'rest_forbidden',
        __( 'REST API доступен только авторизованным пользователям.', 'textdomain' ),
        array( 'status' => 401 )
    );
} );

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

Более аккуратный вариант с исключением для нужных маршрутов

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

<?php
add_filter( 'rest_authentication_errors', function ( $result ) {
    if ( ! empty( $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/posts',
        '/wp-json/wp/v2/pages',
        '/wp-json/my-plugin/v1/public',
    );

    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' => 401 )
    );
} );

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

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

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

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

Что проверить после внедрения

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

  • Откройте /wp-json/ в режиме инкогнито — должен быть отказ или ограниченный ответ, если вы закрыли API полностью.
  • Проверьте /wp-json/wp/v2/posts?per_page=1 — если этот маршрут должен быть публичным, он обязан отвечать.
  • Зайдите в админку и откройте редактор записи — сохранение и автосохранение не должны ломаться.
  • Если есть формы, поиск или внешние сервисы, проверьте их отдельно.

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

curl -I https://example.com/wp-json/
curl -I https://example.com/wp-json/wp/v2/posts?per_page=1

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

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

Сломали Gutenberg или автосохранение

Это самая частая проблема после грубого отключения REST API через .htaccess или серверные правила. Редактор WordPress активно использует REST для сохранения и получения данных. Если закрыть всё подряд, админка перестанет работать корректно.

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

Закрыли публичные маршруты, которые нужны теме или плагину

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

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

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

Ориентировались только на robots.txt

Запись в robots.txt не закрывает доступ. Она лишь просит поисковики не индексировать URL. Если задача именно в ограничении доступа, нужен код, серверное правило или плагин безопасности.

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

Если цель — уменьшить поверхность атаки и лишний шум, не ограничивайтесь только REST API. Посмотрите на соседние точки: xmlrpc.php, публичные авторские архивы, лишние таксономии и служебные страницы. Но не смешивайте всё в одну правку: так проще понять, что именно сломалось.

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

Если вам нужен более широкий набор технических настроек — от дублей и индексации до чистки сайта и служебных ограничений — такие задачи удобно держать в одном месте, например через Clearfy Pro: https://wpshop.ru/plugins/clearfy. Но даже в этом случае логику доступа лучше проверять вручную, а не полагаться только на чекбокс.

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

Как автоматически удалять неиспользуемые плагины в WordPress
05.03.2026
Автоматическое отключение неиспользуемых тем в WordPress
08.02.2026
Как отключить автоматическое масштабирование изображений в WooCommerce
20.04.2026
Как создать автоматический отчет по активности пользователей в WordPress
14.02.2026
Как отключить Gutenberg для отдельных типов записей в WordPress
30.12.2025