#ruby-on-rails #ruby-on-rails-4 #form-for #csrf-protection
#ruby-on-rails #ruby-on-rails-4 #форма- для #csrf-защита
Вопрос:
В моем приложении у меня есть форма для создания города.
Все работает нормально, когда для параметра remote в форме установлено значение false. Однако возникает проблема, когда я меняю его на true.
Когда форма отправляется удаленно, я могу отправить две формы с одним и тем же токеном CSRF и вместо получения ошибки ActionController::InvalidAuthenticityToken для второго запроса. Вторые запросы также создадут объект, чего не должно быть.
Знаете ли вы, что вызывает эту проблему и как я могу ее исправить?
<%= form_for [:administrators,@city],remote: true,:authenticity_token => true do |f| %>
<div class="field">
<%= f.label :province_id,'Select a province' %>
<%= f.select :province_id,options_from_collection_for_select(Province.all, :id,:name, @city.province_id),{ :prompt => 'Select province' } %> <br>
<div class="errors alert-box alert" style="display:none;"></div>
</div>
<div class="field">
<%= f.label :name %>
<%= f.text_field :name%>
<div class="errors alert-box alert" style="display:none;"></div>
</div>
<div class="action">
<% if @city.id? %>
<%= f.submit 'Update', class:'button' %>
<btn class='cancel_form_button button tiny alert'> </btn>
<% else %>
<%= f.submit 'Create', class:'button' %>
<% end %>
</div>
Комментарии:
1. Запросы поступают из вашего кода, и они являются аутентичными. Таким образом, токен выполняет свое обещание. Это не обещает защитить вас от повторных запросов, не так ли?
2. @SergioTulentsev если вы установите для remote значение false, а затем попытаетесь отправить форму во второй раз, вы получите сообщение об ошибке ActionController::InvalidAuthenticityToken
3. Как отправить форму во второй раз, если страница перезагружается?
4. Кроме того, вы проверили сгенерированную форму? есть ли скрытое поле токена в удаленной форме?
5. @SergioTulentsev используя инструмент разработчика FireFox, вы можете редактировать и повторно отправлять запрос. да, токен включен.
Ответ №1:
Правильно ли я понимаю, что вы хотите предотвратить создание city
с теми же параметрами?
Тогда это не ответственность за токен CSRF. CSRF предотвращает запросы от других доменов к вашему серверу, это функция безопасности.
Проверка данных (допуск только одного города с некоторыми конкретными параметрами) является обязанностью по проверке модели. Поэтому вам нужно будет добавить validates_uniqueness_of :name
в свою City
модель. (также вы можете добавить scope: :province_id
опцию). Смотрите http://guides.rubyonrails.org/active_record_validations.html#uniqueness
С другой стороны, если вы просто хотите запретить пользователю время от времени дважды щелкать по отправке, вы можете добавить disable_with
опцию в btn helper, чтобы отключить ее после щелчка (вам нужно будет включить ее обратно в своем коде после ответа)
Комментарии:
1. нет, это не то, что я имел в виду. Я думаю, вы не должны иметь возможности отправлять две формы с одним и тем же токеном CSRF, что возможно в этой ситуации, но невозможно, когда форма не отправляется удаленно.
2. что происходит, когда вы отправляете форму синхронно?
3. Когда я отправляю форму синхронно, если я попытаюсь отправить форму во второй раз с тем же токеном, я получу ошибку InvalidAuthenticityToken