От автора: приветствую вас, друзья. Мы продолжаем цикл статей, посвященных знакомству с фреймворком Yii2. В этой статье мы познакомимся с темой Yii2 CSRF. Мы узнаем, что такое CSRF и каков механизм защиты от данного вида атаки нам предлагает фреймворк.
Начнем мы с того, что же такое CSRF. Собственно, определение всегда можно найти в Википедии. Если говорить своими словами и попроще, то это одна из разновидностей атак, когда от вашего имени может быть отправлен запрос на сайт, пользователем которого вы являетесь.
Одним из вариантов защиты от подделки запроса является специальный токен, который генерируется и отправляется вместе с запросом. На сервере, соответственно, проверяется наличие данного токена в запросе и его корректность. И только в случае успеха данные будут приняты и обработаны. Это если говорить вкратце о сути уязвимости и способе защиты.
Теперь попробуем продемонстрировать как работает Yii с указанным токеном. В качестве примера давайте создадим кнопку, клик по которой будет отправлять AJAX запрос на сервер. Для начала методом GET. Итак, код кнопки в представлении:
1 |
<button class="btn btn-success" id="my-btn">Кнопка</button> |
Теперь в конце файла представления зарегистрируем JavaScript, который будет отправлять нужный нам запрос.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?php $js = <<<JS $('#my-btn').on('click', function(){ $.ajax({ url: '/site/index', type: 'GET', success: function(res){ console.log(res); }, error: function(){ alert('Error!'); } }); }); JS; $this->registerJs($js); ?> |
Простейший запрос, который отправит запрос методом GET и, в случае успеха, ответ выведет в консоль. В SiteController примем этот запрос:
1 2 3 4 5 6 7 |
public function actionIndex() { if(Yii::$app->request->isAjax){ return 'Ответ на запрос'; } return $this->render('index'); } |
Давайте нажмем кнопку и проверим работу скрипта:
Запрос работает — никаких сюрпризов. А теперь попробуем изменить метод с GET на POST:
1 |
type: 'POST', |
В результате у вас может ничего не измениться и вы все также получите ответ. Но можете наблюдать и вот такую картину при следующем клике по кнопке:
Причина «плохого запроса» (в консоли мы видим ошибку 400 Bad Request) как раз и кроется в том, что Yii защищается от подделки запросов и требует озвученного выше csrf-токена. Исправить возникшую проблему можно несколькими способами. Первый из них заключается в отключении проверки csrf-токена (disable). Сделать это можно как на уровне отдельного действия, так и на уровне всего приложения. Давайте отключим его проверку для конкретной страницы. Поместим в нужный нам контроллер следующий код:
1 2 3 4 5 6 7 |
public function beforeAction($action) { if (in_array($action->id, ['index'])) { $this->enableCsrfValidation = false; } return parent::beforeAction($action); } |
Метод beforeAction выполняется перед вызовом любого действия. В данном методе мы проверим текущее действие и, если оно совпадет с заданным (index), тогда мы отключим проверку токена. Проверим, сработает ли данный способ.
Как видим, работает. Но использовать данный способ я рекомендую только там, где проверка токена вам действительно не нужна. На самом деле отключение такой проверки — практически всегда лишнее. Проще добавить проверяемый токен. Сделать это можно всего одной строкой кода в шаблоне. Откроем шаблон \views\layouts\main.php и в тегах head добавим следующую строку кода:
1 |
<?= Html::csrfMetaTags() ?> |
После этого токен будет автоматически отправляться и проверяться на сервере, POST-запрос теперь должен работать без проблем. К слову, метод csrfMetaTags у вас уже вполне мог быть в шаблоне и такой ошибки изначально возникнуть не должно, но теперь вы знаете, как решить проблему проверки CSRF, если столкнетесь с ней.
Больше о фреймворке вы можете узнать из наших бесплатных или платных уроков. Также создание простейшего блога на Yii2 можно посмотреть в этом цикле уроков.