Yii2. Использование csrf-токенов

Главная  >>  Backend  >>  Yii2. Использование csrf-токенов

Первым делом нужно разобраться, что являют собой csrf-токены и почему их использование насколько важно. Об этом подробно расписано в Википедии

Фреймворк Yii2 дает прекрасные возможности по работе с csrf-токенами, при этом их проверка включена по умолчанию. Это означает, что простое использование html-формы

приведет к появлению ошибки

О том, почему так не следует делать и как следует немного ниже. Сначала расскажу, как избавить себя от этой ошибки.
Для этого в конфиге Вашего приложения укажите

Это отключит csrf-валидацию для всего приложения. Если же Вам нужно отключить проверку csrf-токенов в каком-то конкретном месте — используйте следующий код в контроллере:

При всей простоте и очевидности настоятельно не рекомендую отключать и/или обходить проверку csrf. Любая уязвимость, а csrf является именно таковой, — это потенциальное место возникновения проблем с Вашим сайтом и следовательно Вы, своими же руками, их создаете.

Как говорится, не надо так..

Далее о хорошем, о том, как же следует использовать возможности Yii2 в работе с csrf.

Наиболее оптимальный вариант — использовать нативные возможности фреймворка.
Это методы ActiveForm::begin() и Html:beginForm()

При включенном свойстве компонента Request enableCsrfValidation данные методы сами генерируют скрытое поле, которому дается имя и значение для последующей проверки csrf. Т.е. Вы не делаете ни единого дополнительного движения — но при этом безопасность Ваших форм стает на порядок выше.

Если же Вы вынуждены использовать форму без обертки фреймворка — Вам подойдет следующий вариант:

Как видите, имя и значение поля, которые будут использоваться при валидации можно получить вручную, обращаясь к базовым компонентам приложения.

Но и это не все 🙂

Очень большая уязвимость — незащищенные ajax-запросы, при помощи которых злоумышленник может нанести вред Вашему сайту. Но доблестный Yii2 и здесь не оставляет нас в беде.
Для того, чтобы правильно защитить наши асинхронные запросы выполните два следующих действия:
Во-первых, в Вашем слое, точнее в его head-части, добавьте следующий код:

Это выведет meta-теги с названием и значением наших csrf-параметров.
После этого Вы, при помощи JavaScript можете получить доступ к этим значениям. Например, вот так:

Как Вы видите, нам нужно просто обратиться к meta-тегам и забрать с них название и значение нужных csrf-параметров. Далее фреймворк все сделает сам.

На это все. На самом деле вопрос о создании/проверке подлинности csrf очень широк и сложен. Есть множество вариантов реализации и даже в разрезе использования Yii2 есть множество нераскрытых в этой статье нюансов. Но, для большинства случаев приведенных примеров более чем достаточно.


  • Shilin Dmitry

    У токена есть время жизни? Потому, что если страница долго не обновлялась, а потом заполнить форму, то идет проброс на ошибку?

    • http://onfor.info onfor

      Да, конечно. Т.к. они основаны на куках.

      • Shilin Dmitry

        Подкажите, а что мешает кому-то взять токен с исходного кода страницы?

        • http://onfor.info onfor

          Токен перегенерируется при каждо перезагрузке страницы)

  • Nataly Didenko

    Нужен ли csrf на бэкенде, если доступ к каждому действию в контроллерах админки прописан только для определённой роли юзеров? Если да, то почему

    • http://onfor.info onfor

      CSRF нужен в любом случае, ведь он защищает от подделки данных формы. А это серьезная уязвимость, которой не стоит пренебрегать.

      Тем более её включениеотключение не требует от Вас каки-то дополнительных дествий (при работе с ActiveForm или Html::beginForm() ).

  • Александр Вялых

    Большое спасибо за статью

  • Yuriy Gergilenko

    в коде выше есть ошибка:

    ...
    data: {param1: param1, csrfParam : csrfToken}
    ...

    в данном случае содержимое переменной csrfParam не станет именем переменной.
    Я сделал так:

    var csrfParam = yii.getCsrfParam();
    var csrfToken = yii.getCsrfToken()

    var postData = {param1: param1 };
    postData[csrfParam] = csrfToken ;
    ...
    $.ajax({
    data: postData
    ...