Ответ 1
Существует несколько методов, которые при совместном использовании обеспечивают достаточную защиту CSRF.
Уникальный токен
Один, специфичный для сеанса токен, достаточно хорош для большинства приложений. Просто убедитесь, что на вашем сайте нет уязвимостей XSS, в противном случае любая используемая вами технология токена - это отходы.
AJAX вызов для регенерации токена - плохая идея. Кто будет охранять охранников? Если сам вызов AJAX уязвим для CSRF, он как бы побеждает цель. Множественные жетоны с AJAX - это вообще плохая идея. Это заставляет вас сериализовать ваши запросы, т.е. Одновременно разрешается только один запрос AJAX. Если вы готовы жить с этим ограничением, вы можете, возможно, поставить токен для второго вызова AJAX в ответ на первый запрос.
Лично я считаю, что лучше повторить аутентификацию пользователя для критических транзакций и защитить оставшиеся транзакции с помощью токена, специфичного для сеанса.
Пользовательский HTTP-заголовок
Вы можете добавить собственный HTTP-заголовок к каждому из ваших запросов и проверить его присутствие на стороне сервера. Фактический ключ/значение не обязательно должен быть секретным, сервер просто должен убедиться, что он существует во входящем запросе.
Этот подход достаточно хорош, чтобы защитить CSRF в более новых версиях браузеров, однако его возможно слишком обходимо, если у вашего пользователя установлена более старая версия для Flash Player.
Проверка Referrer
Проверка заголовка Referrer также хороша для защиты CSRF в новых браузерах. Невозможно подделать этот заголовок, хотя это возможно в более старых версиях Flash. Таким образом, хотя он не является надежным, он по-прежнему добавляет некоторую защиту.
Решение Captcha
Принуждение пользователя к решению капчей также эффективно против CSRF. Его неудобно, как черт, но довольно эффективно. Это, пожалуй, единственная защита CSRF, которая работает, даже если у вас есть уязвимости XSS.
Резюме
- Использовать токен, основанный на сеансе, но повторно аутентифицировать транзакции с высокой стоимостью.
- Добавьте собственный HTTP-заголовок, а также проверьте наличие ссылки. Оба они не являются безупречными, но не боятся.