Rails — Как добавить защиту CSRF к формам, созданным в javascript?

Я использую backbone.js, и он отлично работает. но в формах, которые я создаю в качестве шаблона javascript, отсутствует токен защиты rails csrf. Как добавить его в шаблоны, которые я создаю в javascript?


person CamelCamelCamel    schedule 14.12.2011    source источник


Ответы (5)


Если у вас где-то в макете есть <%= csrf_meta_tag %> и он доступен вам из js, вы можете получить к нему доступ, используя $('meta[name="csrf-token"]')

См. http://eunikorn.blogspot.com/2011/07/working-with-backbonejs-in-harmony-with.html за идею о том, как внедрить поддержку csrf в каждый магистральный запрос.

person Thong Kuah    schedule 14.12.2011
comment
См. gist.github.com/3482636 для другого примера того, как это можно взломать. У меня нет идея, если это то же самое. - person Chris Pfohl; 19.09.2012
comment
В частности: $.ajax(data: {authenticity_token: $('meta[name="csrf-token"]').attr("content")}) - person Meekohi; 30.08.2018

Лучший способ решить это внутри формы:

<%= hidden_field_tag :authenticity_token, form_authenticity_token %>

Обновлять:

Похоже, что form_authenticity_token является приватным для контроллеров в более новых версиях рельсов.

Если это так для вас, я предлагаю: объявить переменную в контроллере, например: @form_token = form_authenticity_token, и использовать ее в представлении, которое вы ищете.

person lucianosousa    schedule 13.02.2014
comment
Это работает, но почему? Разве form_authenticity_token не является приватным в контроллере? - person Franklin Yu; 28.08.2016
comment
Это не работает для меня Rails 4.2.2. Я получаю: undefined local variable or method 'form_authenticity_token' for #<#<Class:0x007ff80b1d36d8>:0x007ff7eec39b58> - person juliangonzalez; 30.08.2016
comment
Эй, ребята, похоже, что form_authenticity_token закрыто для контроллеров, как сказал Франклин. Я увидел предложение объявить переменную в контроллере @form_token = form_authenticity_token и использовать ее в представлении. - person lucianosousa; 01.09.2016
comment
Это работает для меня в рельсах 4.2.5. Примечание: эта форма была сгенерирована в ERB, а не в JS. - person Jared Menard; 24.10.2017

Вы можете добавить токен csrf к каждой форме, которая использует «опубликовать» или «удалить». Вот это в кофескрипте:

$ -> 
  for f in $("form")
    if f.method == 'post' or f.method == 'delete'
      $(f).prepend("<input type='hidden' name='authenticity_token' value='" + token + "'>")

Убедитесь, что в макете есть ‹%= csrf_meta_tags %>. Он уже должен быть в стандартном макете приложения, но добавьте его, если вы используете другой макет.

person suga_shane    schedule 01.10.2012
comment
Где объявлено token? - person juliangonzalez; 29.08.2016
comment
Что @suga_shane имеет в виду, написав, убедитесь, что у вас есть <%= csrf_meta_tags %>, так это то, что этот помощник Rails сгенерирует для вас токен и вставит его в HTML head. Маркером является атрибут content в теге <meta> с именем csrf-token. - person sameers; 28.07.2017

У меня есть форма внутри компонента Vue в приложении Rails 6.

К моему удивлению, оказалось достаточно включить скрытый ввод с именем authenticity_token в шаблон Vue, и при загрузке страницы Rails заполнил значение токеном защиты CSRF.

E.g.

<template>
  <div id="app">
    <form
      action="/submit"
      method="post"
      @submit.prevent="onSubmit"
    >
      <input
        type="hidden"
        name="authenticity_token"
        value=""
      >
      <!-- rest of form -->
    </form>
  </div>
</template>

Что отображается как:

<div id="app">
  <form action="/submit" method="post">
    <input type="hidden" name="authenticity_token" value="zl9PJiE...">
    ...
  </form>
</div>
person James Hibbard    schedule 23.04.2020

Что касается Rails 4.2.2, вам не разрешено использовать

<%= hidden_field_tag :authenticity_token, form_authenticity_token %>

из вашего файла ресурсов .js.erb.

Однако вы можете создать форму внутри файла .js.erb, а в представлении, содержащем файл формы .html.erb, использовать помощник hidden_field_tag для создания элемента токена. Поскольку этот элемент будет создан вне формы, вы можете использовать jquery для добавления этого элемента в форму.

Практический пример: SweetAlert (первая версия, кажется, версия тоже решила эту проблему)

show.js.erb

$('.js-button-apply-offer').click(function(e) {
var urlOffer = $(this).attr('data-url-offer');
var modalParams = {
    type: 'warning',
    title: 'add file',
    text: '<p>Need to add a file before continuing</p>' // This is a hack for Sweet alert, solved in SweetAlert2 Consider upgrade
    +"<form action='"+urlOffer+"' id='formCustomCV' method='post' enctype='multipart/form-data' data-remote='true'>"
    + "<input type='file' name='custom_cv' id='fileToUploadAlert' accept='application/pdf'>\n"
    +"</form>",
    html: true,
    showCancelButton: true,
    confirmButtonColor: '#DD6B55',
    confirmButtonText: 'Send',
    cancelButtonText: 'Cancel',
    closeOnConfirm: false
  }
swal(modalParams,
function(){
  var form_token = $('#form_token');
  $('#formCustomCV').append(form_token).submit(); //update to submit using ajax
});

показать.html.erb

<%= button_tag t('offers.offer.apply'),
  class: 'center-block btn btn-success js-button-apply-offer',
  id: "js-button-apply-offer",
  data: {
    url_offer: apply_talents_offer_path(@offer),
  } 
%>
<%= hidden_field_tag :authenticity_token, form_authenticity_token, id: :form_token %>
person juliangonzalez    schedule 29.08.2016