2015-11-26 2 views
0

У меня есть одностраничное приложение ROR с большим количеством удаленных форм. Моя проблема заключается в том, что после запроса без idempotent Rails изменяет токен CSRF и аннулирует токен, встроенный в метафайл страницы. Таким образом, повторный неиндемпотентный запрос завершается с ошибкой, если страница не обновляется.Rails автоматически обновляет токен CSRF для повторного запроса JSON

Например, если удаленная форма, отправленная через POST, с ошибками проверки и с повторной отправкой формы, она не выполняется с ошибкой InvalidAuthenticityToken.

Я думаю, эта проблема достаточно распространена для Rails, чтобы обрабатывать ее по умолчанию, но, по-видимому, нет.

+0

Можете ли вы сделать CSRF токен сохраняются? Вам действительно нужен только один токен CSRF на сеанс пользователя, а не на «небезопасный» запрос. – SilverlightFox

+0

@SilverlightFox Сохраняет ли токен CSRF не ниже безопасности приложений? Разве злоумышленник не может захватить токен CSRF и использовать его при выполнении запроса? –

+1

Не совсем, [см. Здесь] (http://security.stackexchange.com/a/22936/8340). Существует некоторый риск для атаки [BREACH attack] (http://breachattack.com/), однако лучше всего отключить любое сжатие по HTTPS. – SilverlightFox

ответ

4

Мое решение этой проблемы, любые pittfalls здесь ?:

application_controller.rb:

class ApplicationController < ActionController::Base 
    protect_from_forgery with: :exception 

    # Devise Authentication, included this line because I know Devise messes 
    # with CSRF token and I'd be appreciate expert opinion on how my solution will 'play' with devise 
    before_action :authenticate_user! 

    # callback to set CSRF TOKEN for non-idempotent ajax request 
    after_action :add_csrf_token_to_json_request_header 

    private 

    def add_csrf_token_to_json_request_header 
    if request.xhr? && !request.get? && protect_against_forgery? 
     response.headers['X-CSRF-Token'] = form_authenticity_token 
    end 
    end 
end 

application.js:

//= require jquery2 
//= require jquery_ujs 
//= require turbolinks= 

$(document).ajaxComplete(function(event, xhr, settings) { 
    header_token = xhr.getResponseHeader('X-CSRF-Token'); 
    if (header_token) $('meta[name=csrf-token]').attr('content', header_token) 
}); 
+0

Спасибо. после одного дня поиска решения я столкнулся с этим, и он работает для меня. мое приложение отключает turbolinks, и поскольку у меня есть одностраничное приложение, мне нужно будет обрабатывать csrf самостоятельно или я получаю ошибку ActionController :: InvalidAuthenticityToken – user664859

Смежные вопросы