В предыдущих частях были описаны создание страницы плагина в админпанели и работа с базой данных с привязкой к этой странице. Теперь рассмотрим не сложный, но при этом необходимый механизм защиты плагина от несанкционированного использования с помощью nonce.
Необходимость защиты
Для того чтобы осознать необходимость защиты достаточно трезво взглянуть на код функции удаления устаревших редакций из базы данных, который был приведён в 3й части.
1 2 3 4 5 6 7 8 9 |
function ClearRevisions() { if (isset($_POST['clean'])) { global $wpdb; $sql = "DELETE posts,rel_ships,meta FROM $wpdb->posts posts LEFT JOIN $wpdb->term_relationships rel_ships ON (posts.ID = rel_ships.object_id) LEFT JOIN $wpdb->postmeta meta ON (posts.ID = meta.post_id) WHERE posts.post_type = 'revision'"; $wpdb->query($sql); }; } |
Эта функция проверяет только установку флажка и ничего больше. Таким образом, открывается возможность выполнить удаление редакций, минуя пользовательский интерфейс плагина и даже авторизацию. Что недопустимо.
Защита с помощью nonce
К счастью, WordPress уже содержит механизм для защиты от подобных ситуаций под названием nonce.
Его суть состоит в том, что перед выполнением какого либо действия генерируется некий псевдослучайный идентификатор. Причём генерация выполняется только для данного конкретного пользователя и только в текущем контексте. Также nonce имеют ограниченное «время жизни», по истечении которого они становятся не действительными.
Обычно nonce используются в виде скрытых полей HTML форм или включаются в URL адреса.
Для того чтобы защитить наш плагин с помощью nonce добавим в HTML форму на его странице в админ панели скрытое поле с помощью функции wp_nonce_field.
1 |
wp_nonce_field( 'cleaning-action' ,'ca_nonce' ); |
Первый параметр функции – название действия, второй параметр – имя самого nonce. Если имя nonce не задано,WordPress присвоит стандартное значение. Однако этого лучше избегать.
В результате, внутри формы появятся скрытые поля с nonce.
1 2 3 4 5 6 |
<form method="post" onsubmit="if (!confirm('Вы уверены?')) {return false}" > <input type="checkbox" name="clean" /><label>Удалить все старые редакции записей и страниц</label><br /> <input type="hidden" id="ca_nonce" name="ca_nonce" value="846d3ac13a" /> <input type="hidden" name="_wp_http_referer" value="/wp-admin/options-general.php?page=TotalOldRevisionsCleaner.php" /> <input type="submit" name="ok" value="Ok" /> </form> |
Далее необходимо выполнить проверку nonce в функции ClearRevisions.
Для примера выполним её наиболее простым и универсальным способом. С помощью функции WordPress wp_verify_nonce (более подробно особенности защиты пользовательского интерфейса работающего в админпанели будут рассмотрены ниже). Для этого необходимо предварительно подключить файл pluggable.php из директории wp-includes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
require_once(ABSPATH.'wp-includes/pluggable.php'); function ClearRevisions() { if (isset($_POST['clean'])) { if (! isset( $_POST['ca_nonce'] ) || ! wp_verify_nonce( $_POST['ca_nonce'], 'cleaning-action' )) { print 'Sorry, an error occurred.'; exit; } else { global $wpdb; $sql= "DELETE posts,rel_ships,meta FROM $wpdb->posts posts LEFT JOIN $wpdb->term_relationships rel_ships ON (posts.ID = rel_ships.object_id) LEFT JOIN $wpdb->postmeta meta ON (posts.ID = meta.post_id) WHERE posts.post_type = 'revision'"; wpdb->query($sql); } } } |
Так работает защита HTML форм. Теперь для того чтобы удалить ненужные редакции из базы данных необходимо предварительно авторизоваться и перейти на страницу плагина в админ панели.
Защита URL строится во многом аналогичным образом. Отличие только в том, что nonse включается не в HTML форму, а в URL страницы при помощи функции wp_nonce_url.
1 |
1="=" 2="wp_nonce_url(" 3="$bare_url," 4="'action'," 5="'my_nonce'" 6="); |
Эта функция принимает три параметра: исходный URL, название действия, имя самого nonce. А, возвращает URL, который содержит в себе параметр nonce.
Особенности защиты страницы плагина в админпанели
Проверять nonce, которые были созданы на страницах админпанели можно двумя способами.
- Универсальный. С использованием функции wp_verify_nonce (пример был приведён выше);
- Специализированный. Предназначенный только для nonce созданных в админпаненли с использованием функции check_admin_referer (также расположена в файле pluggable.php).
Отличие между ними в том, что функция check_admin_referer дополнительно проверяет ещё и HTTP referer. Это предотвращает передачу даже корректного nonce со страницы, которая не относится к админпанели WordPress. Тем самым обеспечивается более высокий уровень безопасности.
Поэтому, для плагинов предназначенных для работы в составе открытых интернет ресурсов данный способ является наиболее предпочтительным.
Кроме того при его использовании значительно сокращается объём кода. Если проверка nonce завершится неудачей, функция check_admin_referer сама выдаст сообщение об ошибке.
Перепишем приведённый выше пример с применением второго способа.
Функция check_admin_referer принимает два параметра: название действия и имя nonce (если используется стандартное имя параметр не обязателен).
1 2 3 4 5 6 7 8 9 10 11 12 13 |
require_once(ABSPATH.'wp-includes/pluggable.php'); function ClearRevisions() { if (isset($_POST['clean'])) { if ( isset( $_POST['ca_nonce'] ) && check_admin_referer( 'cleaning-action', 'ca_nonce' )) { global $wpdb; $sql= "DELETE posts,rel_ships,meta FROM $wpdb->posts posts LEFT JOIN $wpdb->term_relationships rel_ships ON (posts.ID = rel_ships.object_id) LEFT JOIN $wpdb->postmeta meta ON (posts.ID = meta.post_id) WHERE posts.post_type = 'revision'"; $wpdb->query($sql); } } } |
Теперь защита плагина стала гораздо надёжнее.
Особенности защиты страниц использующих AJAX
Для проверки nonce полученных с помощью AJAX используется специальная функция check_ajax_referer (также расположена в файле pluggable.php). Она принимает те же параметра, что и check_admin_referer полюс третий параметр die.
Этот параметр определяет будет ли завершаться выполнение кода с выдачей сообщения об ошибке в случае неудачной проверки nonce. Этот параметр имеет значение по умолчанию (true) и не является обязательным.
Несмотря на своё название, эта функция проверяет только сам nonce.
Репозиторий WordPress
Важно особо отметить. Разработчики WordPress довольно трепетно относятся к вопросам связанным с безопасностью. Поэтому, если Вы планируете добавить Ваш плагин в репозиторий WordPress наличие подобной защиты строго обязательно.
Ссылки
Добавить комментарий