WordPress: Nonces (нонсы)

· WordPress, Безопасность и Разработка плагинов · 3 мин чтения

Nonce (произносится как «нонс») — это сгенерированные числа, используемые для подтверждения точки запроса с целью проверки на безопасность. Каждый nonce может быть использован только один раз.

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

Как пользоваться nonce?

Давайте возьмем пример описанный выше, который связан с отправкой формы пользователем. Следующим этапом будет добавление nonce.

Nonce позволяет понлять, что пользователь действительно хотел это сделать, а не какое-то третье лицо. А что если кто-то пытался обмануть вас и случайным образом вы удалили пост.

Nonce в данном случае используется для сравнения действий пользователи, правда ли он хотел удалить пост или нет.

Когда вы генерируете ссылку, используйте функцию wp_create_nonce() для добавления нонса к ссылке. Аргумент добавленный к функции, будет использоваться в целях создания уникального значения, который не повториться для текущего, конкретного события.

В дальнешем, когда вы обрабатываете ссылку удаления, вам нужно проверить, что отправленный nonce — это именно то, что вы ожидаете.

Для того, чтобы более углубленно изучить нонсы, предлагаю прочитать пост от Марка Якита. Она написана на английском, но используя переводчик, например в Google Chrome, её можно понято достаточно точно.

Полный пример

Полный пример с использовать нонсев, их проверкой, проверкой вводных и выводимых данных смотрите ниже:

<?php
/**
 * генерация ссылки удаления
 */
function wporg_generate_delete_link($content)
{
    // добавить только для открытой записи
    if (is_single() && in_the_loop() && is_main_query()) {
        // добавить доп. параметры к ссылке: action, post, nonce
        $url = add_query_arg(
            [
                'action' => 'wporg_frontend_delete',
                'post'   => get_the_ID(),
                'nonce'  => wp_create_nonce('wporg_frontend_delete'),
            ],
            home_url()
        );
        return $content . ' <a href="' . esc_url($url) . '">' . esc_html__('Delete Post', 'wporg') . '</a>';
    }
    return null;
}
 
/**
 * обработка запроса
 */
function wporg_delete_post()
{
    if (
        isset($_GET['action']) &&
        isset($_GET['nonce']) &&
        $_GET['action'] === 'wporg_frontend_delete' &&
        wp_verify_nonce($_GET['nonce'], 'wporg_frontend_delete')
    ) {
 
        // проверка на существование id поста
        $post_id = (isset($_GET['post'])) ? ($_GET['post']) : (null);
 
        // проверка если ID поста существует
        $post = get_post((int)$post_id);
        if (empty($post)) {
            return;
        }
 
        // удалить пост
        wp_trash_post($post_id);
 
        // перенаправить в админ панель
        $redirect = admin_url('edit.php');
        wp_safe_redirect($redirect);
 
        // мы закончили
        die;
    }
}
 
if (current_user_can('edit_others_posts')) {
    /**
     * добавить ссылку удаления после текста поста
     */
    add_filter('the_content', 'wporg_generate_delete_link');
 
    /**
     * зарегистрируем наш обработчик в init хук
     */
    add_action('init', 'wporg_delete_post');
}