Перевірка прав
Щоб запобігти зміні налаштувань плагіна або заборонити переглядати дані, доступу до яких у користувача немає, потрібно перевіряти права користувача, здійснювати будь-яку дію.
У WordPress для цього є два підходи:
- перевірка можливостей (прав) користувача.
- одноразові числа (nonce).
Це різні підходи та одноразові числа, як правило, доповнюють перевірку прав.
У цьому розділі поговоримо про перший: «Перевірка прав користувача».
Можливості користувача (перевірка прав)
Перевірка прав – це основний і мабуть фундаментальний момент у захисті та безпеці плагіна. Він перевіряє можливість користувача робити щось. У кожного користувача є роль (Підписчик, Автор, Редактор) і кожна роль має набір прав. За допомогою функції current_user_can() ми можемо перевірити, чи має поточний користувач зазначене право, наприклад manage_options
(право адміністратора змінювати опції сайту). Якщо користувач має право, то функція поверне true і умова для виконання якогось коду буде виконано і навпаки – якщо права немає, код виконуватися не буде.
Наприклад, автор може публікувати та редагувати записи, але не має права редагувати чужі записи. А «Редактор» може публікувати та змінювати свої та чужі записи. Але жоден з них не може змінювати налаштування сайту, як це може робити адміністратор. Залежно від можливостей кожної ролі, адмін-панель WordPress виглядатиме по-різному: наприклад, у «Автора» будуть одне меню, а у «Адміністратора» воно буде інше – значно розширено.
Список усіх прав, залежно від ролі користувача, ви знайдете в описі функції current_user_can() .
Перевірка прав користувача на прикладі
При створенні плагіна, потрібно приділяти пильну увагу ролям, яким мають бути дозволені виконання певних дій.
Наприклад, давайте подивимося на небезпечний код без перевірки прав і що поганого в результаті може вийти. Приклад нижче показує функцію, яка, за задумом, повинна давати можливість «Редактору» видаляти записи на фронтенді сайту:
## функція виводить посилання на видалення поточного запису function frontend_delete_link(){ $url = add_query_arg( array( 'action'=> 'frontend_delete_link', 'post'=> get_the_ID() ), home_url(), ); echo "<a href='{$url}'>Видалити</a>"; }
Тепер уявимо, ми використали цю функцію і вивели посилання десь у фронті. При натисканні на неї спрацьовуватиме наступний код обробки запиту видалення запису:
## Функція видаляє вказаний у $_REQUEST['post'] запис function frontend_delete_post(){ // Визначимо ID запису $post_id = ( isset( $_REQUEST['post'] ) ? get_post( (int) $_REQUEST['post'] ) : false; // Немає запису - виходимо... if( empty($post_id) ) return; // Видаляємо запис wp_trash_post($post_id); // Перенаправляємо на сторінку адмінки $redirect = admin_url('edit.php'); wp_safe_redirect ($ redirect); exit; } // Включаємо обробник if( isset($_REQUEST['action']) && $_REQUEST['action']=='frontend_delete_link' ) { add_action('init', 'frontend_delete_post'); }
Код вище дозволяє будь-якому відвідувачу сайту, натиснути на посилання “Видалити” та видалити пост. А треба, щоб таку можливість мали користувачі за участю «Редактор» або старшою роллю, наприклад, «Адміністратор». Якщо будь-хто зможе це зробити, то ви зрештою залишитеся без контенту.
Для цього давайте змінимо код посилання і не виводитиме посилання для ролей молодше редактора:
function frontend_delete_link(){ // виходимо якщо немає права 'edit_others_posts', яке має Редактори і старші ролі. if( ! current_user_can( 'edit_others_posts' ) ) return; $url = add_query_arg( array( 'action'=> 'frontend_delete_link', 'post'=> get_the_ID() ), home_url(), ); echo "<a href='{$url}'>Видалити</a>"; }
Також таку перевірку потрібно додати під час виконання самої операції видалення:
## Функція видаляє вказаний у $_REQUEST['post'] запис function frontend_delete_post(){ // Визначимо ID запису $post_id = ( isset( $_REQUEST['post'] ) ? get_post( (int) $_REQUEST['post'] ) : false; // Немає запису - виходимо... if( empty($post_id) ) return; // виходимо якщо немає права 'edit_others_posts', яке має Редактори і старші ролі. if( ! current_user_can( 'edit_others_posts' ) ) return; // Видаляємо запис wp_trash_post($post_id); // Перенаправляємо на сторінку адмінки $redirect = admin_url('edit.php'); wp_safe_redirect ($ redirect); exit; } // Включаємо обробник if( isset($_REQUEST['action']) && $_REQUEST['action']=='frontend_delete_link' ) { add_action('init', 'frontend_delete_post'); }
В обох випадках ми підтверджуємо, що поточний користувач має можливість edit_others_posts
, яка може бути лише у «Редакторів» або ролей старших. Якщо такої можливості немає, ми нічого не робимо.
Логіка перевірки прав досить проса і зрозуміла. Варіантів де це потрібно дуже багато. І майже завжди використовується функція current_user_can() .
Одноразові числа
Перевірка прав – це перший та основний рівень захисту. Він дозволяє або забороняє поточному користувачеві заходити на сторінки, бачити частини контенту та виконувати будь-які дії. Але такий захист не ідеальний… Чому? Читайте у розділі «Одноразові числа» .