csrf валидация - "не удалось проверить данные"

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
voodooism
Сообщения: 48
Зарегистрирован: 2018.11.12, 10:29

csrf валидация - "не удалось проверить данные"

Сообщение voodooism »

На проекте при отправке формы периодически возникает ошибка csrf валидации

Код: Выделить всё

yii\web\BadRequestHttpException: Не удалось проверить переданные данные. in /var/www/moeirc/vendor/yiisoft/yii2/web/Controller.php:166
Форма достаточно простая, содержит в себе всего несколько полей, никакой сложной логики или отправки файлов. Отправляется с помощбю ajax
Ошибка возникает достаточно редко, и я никак не могу выявить причину.
На данный момент известно, что ошибка происхоидит независимо от данных отправленных в форме, ситуация когда пользователь открыл страницу в нескольких окнах, и спустя некоторое время пытается отправить форму тоже исключается, ситуация когда форма загружена, а отправка происходит через какое то продолжительное время - так же исключена. Максимальное зафиксированое время между загрузкой и отправкой формы ~2000 секунд, хотя ошибка бывает и при ~150-200 секундах. На локальном сервере воспроизвести ошибку не получается :(

Пока что на ум приходит только следующее:
Проект загружен на 2ух фронт-энд серверах(nginx) и 4х бэкэндах. Может ли происходить такая ситуация, когда форма загружается с одного бэкэнда, а отправляется на другой бэкэнд? Я не совсем разобрался как генерурется csrf параметр на сервере, но возможен ли из-за этого конфликт? Хотя, судя по настройкам csrf параметр хранится в куках у клиента, а не в сессии сервера. Если ошибка происходит именно из-за этого, то какие могут быть пути решения проблемы?

Проект собран на basic шаблоне, вот настройка компонента request.

Код: Выделить всё

        'request' => [
            'cookieValidationKey' => '_OgryIAX7GtLaeqeVFNyZJNIrqmeVzmR',
            'csrfParam' => 'project/name',
        ],
Так же, хочу добавить что форма генерурется с помощью ActiveForm и csrf парметры всегда прописываются в вёрстке.
<?= Html::csrfMetaTags() ?> так же присутствует в лейауте
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: csrf валидация - "не удалось проверить данные"

Сообщение samdark »

Проект загружен на 2ух фронт-энд серверах(nginx) и 4х бэкэндах. Может ли происходить такая ситуация, когда форма загружается с одного бэкэнда, а отправляется на другой бэкэнд?
Да, вполне. У вас сессии в одном хранилище на обоих бэкендах?
Хотя, судя по настройкам csrf параметр хранится в куках у клиента, а не в сессии сервера.
И там и там. Затем они сравниваются.
voodooism
Сообщения: 48
Зарегистрирован: 2018.11.12, 10:29

Re: csrf валидация - "не удалось проверить данные"

Сообщение voodooism »

samdark писал(а): 2019.03.15, 16:23
Проект загружен на 2ух фронт-энд серверах(nginx) и 4х бэкэндах. Может ли происходить такая ситуация, когда форма загружается с одного бэкэнда, а отправляется на другой бэкэнд?
Да, вполне. У вас сессии в одном хранилище на обоих бэкендах?
Хотя, судя по настройкам csrf параметр хранится в куках у клиента, а не в сессии сервера.
И там и там. Затем они сравниваются.
Я правильно понял, что проверить это можно, например, настроив хранение сессий в редисе?
Т.е. если писать сессии в редис, и ошибки не будет - значит проблема была в этом ?

И второй вопрос, может ли помочь то что предложил картик?

Пихнуть в лейаут следующее:

Код: Выделить всё

$js = <<< JS
(function() {
    var send = XMLHttpRequest.prototype.send,
        token = document.getElementsByTagName('meta')['csrf-token'].content;
    XMLHttpRequest.prototype.send = function() {
        this.setRequestHeader('X-CSRF-Token', token);
        return send.apply(this, arguments);
    };
}());
JS;
$this->register($js, \yii\web\View::POS_HEAD);
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: csrf валидация - "не удалось проверить данные"

Сообщение samdark »

Т.е. если писать сессии в редис, и ошибки не будет - значит проблема была в этом ?
Да.
И второй вопрос, может ли помочь то что предложил картик?
Может если вы делали POST запросы XMLHttpRequest не передавая при этом токена.
voodooism
Сообщения: 48
Зарегистрирован: 2018.11.12, 10:29

Re: csrf валидация - "не удалось проверить данные"

Сообщение voodooism »

samdark писал(а): 2019.03.18, 12:38
Т.е. если писать сессии в редис, и ошибки не будет - значит проблема была в этом ?
Да.
И второй вопрос, может ли помочь то что предложил картик?
Может если вы делали POST запросы XMLHttpRequest не передавая при этом токена.
Писать сессии в редис не помогло :(

Ну явно я ничего не передавал, я просто в ajax в data передаю сериализованную форму. Но, на сколько я понимаю и вижу в верстке - active form создает hidden-поле с токеном. То есть откуда взятся этой ошибке впринципе?
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: csrf валидация - "не удалось проверить данные"

Сообщение samdark »

Попробуйте слогировать передаваемые данные, значение куки и сессии. Есть ли полный набор токенов?
voodooism
Сообщения: 48
Зарегистрирован: 2018.11.12, 10:29

Re: csrf валидация - "не удалось проверить данные"

Сообщение voodooism »

samdark писал(а): 2019.03.18, 14:50 Попробуйте слогировать передаваемые данные, значение куки и сессии. Есть ли полный набор токенов?
https://pastebin.com/uFhazjF9 Вот такие ошибки

Добавил в ajax-запрос который порождает ошибку заголовок X-CSRF-Token. Не помогает :(

Код: Выделить всё

      headers: {
                  'X-CSRF-Token' : $('meta[name=csrf-token]').attr('content')
                },
Ответить