Как правильно настроить AJAX nonce для WordPress REST API?
Следуя комментарию с ссылкой здесь, который привел меня к этой документации, я попытался настроить nonce для аутентификации пользователя.
Я добавил:
wp_localize_script( 'wp-api', 'wpApiSettings', array(
'root' => esc_url_raw( rest_url() ),
'nonce' => wp_create_nonce( 'wp_rest' )
) );
в условие if, проверяющее, что пользователь вошел в систему и может выполнять действия, запрашиваемые в REST вызове.
Я также добавил:
beforeSend: function ( xhr ) {
xhr.setRequestHeader( 'X-WP-Nonce', wpApiSettings.nonce );
},
в свой jQuery класс для API вызова.
Я получил ошибку, сообщающую, что wpApiSettings не существует. Что я сделал не так?

Для начала...
(Эта информация для тех читателей, кто еще не знает об этом.) Существует два способа аутентификации REST API запросов:
Использование стандартной аутентификации через куки
Использование плагина, такого как Application Passwords
Подробнее можно прочитать в официальном руководстве по REST API здесь, а этот ответ посвящен стандартной аутентификации через куки, где nonce должен быть передан либо через параметр запроса GET/POST
с именем _wpnonce
, либо через (пользовательский HTTP) заголовок с именем X-WP-Nonce
.
Варианты отправки nonce через куки
Простой вариант: Добавить
_wpnonce
в URL конечной точки REST API. Работает с запросамиGET
,POST
и другими, включая JSON-данные.jQuery.ajax({ method: 'POST', // _wpnonce как параметр GET/$_GET запроса url: '/path/to/endpoint?_wpnonce=<nonce>', data: { foo: 'bar', baz: 1 }, dataType: 'json', success: function ( data ) { console.log( data ); }, });
Или добавить
_wpnonce
в тело запроса.jQuery.ajax({ method: 'POST', url: '/path/to/endpoint', // _wpnonce как параметр POST/$_POST запроса // но может быть GET; смотрите параметр `method` выше, который по умолчанию GET, если не указан data: { foo: 'bar', baz: 1, _wpnonce: '<nonce>' }, dataType: 'json', success: function ( data ) { console.log( data ); }, });
Или, особенно при отправке JSON-данных (как в примере кода в этом вопросе): Добавить
X-WP-Nonce
в заголовки запроса. Этот вариант также хорошо работает с запросамиGET
,POST
и другими.jQuery.ajax({ method: 'POST', url: '/path/to/endpoint', data: JSON.stringify( { foo: 'bar', baz: 1 } ), // отправка строки в формате JSON contentType: 'application/json; charset=utf-8', // и заголовок Content-Type для JSON // Отправить nonce как часть заголовков. beforeSend: function ( xhr ) { xhr.setRequestHeader( 'X-WP-Nonce', '<nonce>' ); }, dataType: 'json', success: function ( data ) { console.log( data ); }, });
Теперь пример:
PHP часть: (в файле функций вашей темы или файле плагина)
// Регистрация тестовой конечной точки REST API..
add_action( 'rest_api_init', 'my_register_rest_routes' );
function my_register_rest_routes() {
register_rest_route( 'my-plugin/v1', '/foo', [
'methods' => 'POST',
'callback' => function ( $request ) {
return [
$request->get_params(),
'Пользователь авторизован: ' . ( is_user_logged_in() ? 'Да' : 'Нет' ),
'Может ли пользователь публиковать записи: ' . ( current_user_can( 'publish_posts' ) ? 'Да' : 'Нет' )
];
},
] );
}
add_action( 'wp_enqueue_scripts', 'my_enqueue_scripts' );
function my_enqueue_scripts() {
// Подключение скрипта, который делает AJAX запрос к /wp-json/my-plugin/v1/foo.
wp_enqueue_script( 'my-script', '/path/to/my-script.js', [ 'jquery' ] );
// Регистрация пользовательских переменных для AJAX скрипта.
wp_localize_script( 'my-script', 'myScriptVars', [
'root' => esc_url_raw( rest_url() ),
'nonce' => wp_create_nonce( 'wp_rest' ),
] );
}
Примечания:
Помните, что первый параметр для
wp_enqueue_script()
—my-script
в примере выше — должен совпадать с первым параметром дляwp_localize_script()
. Этот параметр является уникальным идентификатором (handle) скрипта, который вы подключаете или локализуете.Если эти параметры не совпадают, скрипт не будет локализован, и JS объект —
myScriptVars
в примере выше — будетundefined
, что может привести к ошибке, такой как упомянутая в вопросе ("wpApiSettings does not exist"). :)
JS часть: (в файле my-script.js
или другом, в зависимости от названия...)
Здесь мы добавляем _wpnonce
в тело запроса.
jQuery.ajax({
method: 'POST',
url: myScriptVars.root + 'my-plugin/v1/foo',
data: { foo: 'bar', baz: 1, _wpnonce: myScriptVars.nonce },
dataType: 'json',
success: function ( data ) {
console.log( data );
},
});
Примечания:
Код выше, как и другой JS код в этом ответе, использует jQuery ajax()
.

Ах, конечно! Я чувствую себя таким глупым, конечно, локализация должна быть выполнена до заголовков. Блин. Отличный ответ.

Заметка для самых медленных среди нас (вроде меня) - первый параметр wp_localize_script
- это handle, с которым вы зарегистрировали свой скрипт при его постановке в очередь.
