Вопрос или проблема
Резюме
Я хочу включить форму на страницу WordPress, которая будет содержать поле nonce, и при отправке она будет проверять nonce, и чтобы это работало правильно при использовании кэширования всей страницы.
Проблема с кэшированием всей страницы
Это работает до тех пор, пока сайт использует механизм кэширования всей страницы, так как код страницы кэшируется, включая поле nonce.
Если кэш не настроен на регенерацию каждые 10 часов или менее, то при отправке формы nonce станет недействительным. 10 часов или менее основано на этой информации, которая относится к плагину WP Rocket, но кажется, что это касается большинства механизмов кэширования.
Поэтому, если вы хотите включить форму на страницу WordPress и проверить nonce на сайте с включенным кэшированием всей страницы, каково решение? Единственный способ — настроить кэш на регенерацию каждые 10 часов или менее?
Примечание: я хочу сделать проверку nonce, отчасти потому, что при запуске WordPress Coding Standards phpcs (код-сниффер) он будет подчеркивать ошибку, что поля формы, подаваемые на отправку, должны быть проверены с помощью nonce.
Пример:
Вот очень простой пример формы, которую я включил в верхнюю часть страниц WordPress, поле nonce генерируется и включается в форму через wp_nonce_field
, при отправке будет отображено уведомление “Nonce недействителен”, если nonce не может быть проверен.
-
На веб-сайтах без кэширования всей страницы nonce действителен
-
На веб-сайтах с полным кэшированием nonce недействителен, если страница, обслуживаемая из кэша, старше 10 часов
function test_form() { ?> <form method="post"> <label for="fname">Имя:</label><br> <input type="text" id="fname" name="fname" value="Джон"><br> <label for="lname">Фамилия:</label><br> <input type="text" id="lname" name="lname" value="Доу"><br><br> <?php wp_nonce_field( 'test_form', 'test_form_nonce' ); ?> <input type="submit" value="Отправить"> </form> <?php if ( !wp_verify_nonce( sanitize_key( $_POST['test_form_nonce'] ), 'test_form' ) ) { echo 'Nonce недействителен'; } } add_action( 'wp_head', 'test_form' );
Общая рекомендация — использовать JavaScript с AJAX для динамического заполнения nonce (не тестировалось):
add_action( 'wp_ajax_nopriv_nonce', static function () : string {
echo wp_create_nonce( 'test_form' );
} );
Ссылка https://stackoverflow.com/questions/43557755/how-to-call-ajax-in-wordpress о том, как сделать AJAX вызов.
let nonce = value_from_ajax_call;
document.querySelector( '#test_form_nonce' ).attr( 'value', nonce );
Ответ или решение
Решение проблемы просроченных нонсов в формах при использовании кеширования целых страниц
Когда вы добавляете форму с полем nonce на страницы, используя WordPress, важно учитывать, что при включенном механизме кеширования целых страниц, значения nonce могут просрочить и стать недействительными. При этом, кеширование может сохранить форму с устаревшим nonce и привести к ошибкам при её отправке. Рассмотрим подробно, как можно решить эту проблему без изменения конфигурации кеша.
Понимание проблемы
Nonce (номинальное число) на самом деле является мерой безопасности, которая защищает от злоумышленников отправки фейковых данных. В WordPress nonce имеет срок действия и, как правило, истекает через 24 часа. Однако, наличие кеширования целых страниц может привести к ситуации, когда пользователь получает форму с устаревшим nonce. То есть, если страница кешируется и остается неизменной в течение более чем 10 часов, то пользователь столкнется с проблемой недействительного nonce при попытке отправить форму.
Решения
1. Использование AJAX для динамического получения nonce
Одним из наиболее эффективных способов решения проблемы является использование AJAX для динамической подстановки nonce в форму. Это позволяет обновлять значение nonce каждый раз, когда пользователь загружает страницу, исключая возможность использования устаревших нонсов.
Пример реализации:
- Создание AJAX-обработчика в функции WordPress:
add_action( 'wp_ajax_nopriv_get_nonce', function() {
echo wp_create_nonce( 'test_form' );
wp_die(); // требуется для завершения работы AJAX запроса
});
- JavaScript для вызова AJAX и обновления значения nonce:
Создайте файл JavaScript или добавьте код в существующий, который будет вызывать AJAX-обработчик:
document.addEventListener('DOMContentLoaded', function() {
fetch('/wp-admin/admin-ajax.php?action=get_nonce')
.then(response => response.text())
.then(nonce => {
document.querySelector('#test_form_nonce').value = nonce; // Обновляем значение nonce
});
});
- Форма с nonce:
Обновите вашу форму, чтобы она правильно отображала поле nonce:
function test_form() {
?>
<form method="post">
<label for="fname">Имя:</label><br>
<input type="text" id="fname" name="fname" value="John"><br>
<label for="lname">Фамилия:</label><br>
<input type="text" id="lname" name="lname" value="Doe"><br><br>
<input type="hidden" id="test_form_nonce" name="test_form_nonce">
<input type="submit" value="Отправить">
</form>
<?php
if ( !wp_verify_nonce( sanitize_text_field( $_POST['test_form_nonce'] ), 'test_form' ) ) {
echo 'Nonce недействителен';
}
}
add_action('wp_head', 'test_form');
2. Обновление нонсов на сервере
Если вы предпочитаете не использовать AJAX, вы могли бы попробовать генерировать новые nonce на сервере перед отображением формы. Для этого, добавьте логику на серверной стороне для обновления nonce перед формой при каждом запросе. Однако, это меньше предпочтительный вариант по сравнению с AJAX, так как это потребует изменения конфигурации кеша.
Заключение
Применение AJAX для динамической генерации nonce при помощи JavaScript — это не только простой и элегантный способ решения проблемы невалидных нонсов, но и способ улучшения пользовательского опыта. Такой метод позволяет избежать необходимости переписывать настройки кеша и обеспечивает максимальную безопасность при работе с формами в WordPress.
Соблюдая эти рекомендации, вы сможете увереннее работать с формами, даже в условиях активного кеширования страниц.