Как отключить/закрыть REST API от публичного доступа?
Я уже отвечал на вопрос как полностью отключить REST API.
Однако разработчики WordPress настоятельно НЕ рекомендуют полностью отключать REST API, потому что это поломает работоспособность WordPress в админке с 5 версии, REST там используется для Блочного редактора контента записи.
Чтобы оставить REST API работоспособным, но при этом закрыть все маршруты от публичного доступа, можно использовать хуки. Тут есть несколько вариантов:
Вариант 1:
# Закрывает все маршруты REST API от публичного доступа
add_filter( 'rest_authentication_errors', function( $result ){
if( is_null( $result ) && ! current_user_can('edit_others_posts') ){
return new WP_Error( 'rest_forbidden', 'You are not currently logged in.', [ 'status'=>401 ] );
}
return $result;
} );
Код можно вставить в файл темы functions.php или куда-либо еще.
Этот код разрешает доступ к REST API только для авторизованных пользователей с правами редактора и выше.
Проверку ! current_user_can('edit_others_posts') можно заменить на более подходящую для вашего сайта. Например, её можно упростить и сделать REST API доступным для всех авторизованных пользователей (неважно какие права). Для этого замените проверку на ! is_user_logged_in().
ВАЖНО! Закрывать маршруты таким образом опасно, потому что на сайте могут быть маршруты для пользователей, например сабмит формы на фронте. Этот метод закроет абсолютно все маршруты в том числе и те, которые могут быть созданы плагинами или темой для неавторизованных пользователей. Поэтому рекомендую использовать вариант ниже через хук rest_pre_dispatch, он позволяет закрыть указанные маршруты и не трогать остальные.
Вариант 2:
Очень похож на первый, но там у нас нет доступа к запросу и классу REST сервера.
Сразу же после хука rest_authentication_errors (если проверка пройдена), запускается метод
WP_REST_Server::dispatch() и в его начале срабатывает хук rest_pre_dispatch. Технически это точно такой же хук, на котором можно вернуть WP_Error и любой рест запрос увидит эту ошибку. Т.е. первый вариант мы можем записать следующим кодом, в котором нам будут доступны объект сервера ($rest_server) и объект запроса ($request). Это в свю очередь позволить закрыть группу роутов по неймспейсу или конкретные роуты:
add_filter( 'rest_pre_dispatch', 'close_rest_api_routes', 10, 3 );
/**
* Close REST API routes from public access.
*
* @param WP_REST_Response|WP_Error|null $result
* @param WP_REST_Server $rest_server
* @param WP_REST_Request $request
*
* @return WP_Error
*/
function close_rest_api_routes( $result, $rest_server, $request ){
// maybe authentication error already set
if( ! is_null( $result ) ){
return $result;
}
if(
// only for `/wp/v2` namespace
'/wp/v2' === substr( $request->get_route(), 0, 6 )
// Administrator
&& ! current_user_can( 'manage_options' )
){
return new WP_Error( 'rest_not_logged_in', 'Your capability is low.', [ 'status' => 401 ] );
}
return $result;
}
Вариант 3:
Используйте плагин Disable WP REST API