Предупреждение: не удается проверить подлинность маркера CSRF rails
Я посылаю данные из представления в контроллер с Ајахи я получил эту ошибку:
предупреждение: не удается проверить подлинность токена CSRF
Я думаю, что я должен отправить этот маркер с данными.
кто-нибудь знает как я могу это сделать ?
редактировать: мое решение
Я сделал это, поместив следующий код в AJAX-ответа:
headers: {
'X-Transaction': 'POST Example',
'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
},
17 ответов:
вы должны сделать это:
убедитесь, что у вас есть
<%= csrf_meta_tag %>
в форматедобавить
beforeSend
для всех запросов ajax, чтобы установить заголовок, как показано ниже:
$.ajax({ url: 'YOUR URL HERE', type: 'POST', beforeSend: function(xhr) {xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))}, data: 'someData=' + someData, success: function(response) { $('#someDiv').html(response); } });
для отправки токена во всех запросах вы можете использовать:
$.ajaxSetup({ headers: { 'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content') } });
лучший способ, чтобы сделать это на самом деле просто использовать
<%= form_authenticity_token.to_s %>
чтобы распечатать маркер непосредственно в коде rails. Вам не нужно использовать javascript для поиска DOM для токена csrf, как упоминают другие сообщения. просто добавьте опцию заголовков, как показано ниже;$.ajax({ type: 'post', data: $(this).sortable('serialize'), headers: { 'X-CSRF-Token': '<%= form_authenticity_token.to_s %>' }, complete: function(request){}, url: "<%= sort_widget_images_path(@widget) %>" })
Если я правильно помню, вы должны добавить следующий код в вашу форму, чтобы избавиться от этой проблемы:
<%= token_tag(nil) %>
Не забудьте параметр.
Ugrading из старого приложения в rails 3.1, включая метатег csrf, все еще не решает его. О том, что rubyonrails.org блог, они дают некоторые советы по обновлению, и в частности эту строку jquery, которая должна идти в разделе head вашего макета:
$(document).ajaxSend(function(e, xhr, options) { var token = $("meta[name='csrf-token']").attr("content"); xhr.setRequestHeader("X-CSRF-Token", token); });
взято из этого сообщения в блоге: http://weblog.rubyonrails.org/2011/2/8/csrf-protection-bypass-in-ruby-on-rails.
в моем случае сеанс сбрасывался при каждом запросе ajax. Добавление выше код решил эту проблему.
действительно самый простой способ. Не беспокойтесь об изменении заголовков.
убедитесь, что у вас есть:
<%= csrf_meta_tag %> in your layouts/application.html.erb
просто сделайте скрытое поле ввода так:
<input name="authenticity_token" type="hidden" value="<%= form_authenticity_token %>"/>
или если вы хотите сообщение jQuery ajax:
$.ajax({ type: 'POST', url: "<%= someregistration_path %>", data: { "firstname": "text_data_1", "last_name": "text_data2", "authenticity_token": "<%= form_authenticity_token %>" }, error: function( xhr ){ alert("ERROR ON SUBMIT"); }, success: function( data ){ //data response can contain what we want here... console.log("SUCCESS, data="+data); } });
- убедитесь, что у вас есть
<%= csrf_meta_tag %>
в формате- добавить
beforeSend
чтобы включить csrf-токен в запрос ajax для установки заголовка. Это требуется только дляpost
запросы.код для чтения csrf-токена доступен в
rails/jquery-ujs
, так что имхо проще всего просто использовать это, следующим образом:$.ajax({ url: url, method: 'post', beforeSend: $.rails.CSRFProtection, data: { // ... } })
Я просто подумал, что свяжу это здесь, поскольку в статье есть большая часть ответа, который вы ищете, и это также очень интересно
лучшие проголосовали ответы здесь правильные, но не будет работать, если вы выполняете кросс-домен запросы, потому что сеанс не будет доступен, если вы явно не скажете jQuery передать cookie сеанса. Вот как это сделать:
$.ajax({ url: url, type: 'POST', beforeSend: function(xhr) { xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content')) }, xhrFields: { withCredentials: true } });
вы можете написать его глобально, как показано ниже.
нормальный JS:
$(function(){ $('#loader').hide() $(document).ajaxStart(function() { $('#loader').show(); }) $(document).ajaxError(function() { alert("Something went wrong...") $('#loader').hide(); }) $(document).ajaxStop(function() { $('#loader').hide(); }); $.ajaxSetup({ beforeSend: function(xhr) {xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))} }); });
Кофе Скрипт:
$('#loader').hide() $(document).ajaxStart -> $('#loader').show() $(document).ajaxError -> alert("Something went wrong...") $('#loader').hide() $(document).ajaxStop -> $('#loader').hide() $.ajaxSetup { beforeSend: (xhr) -> xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content')) }
упс..
я пропустил следующую строку в моем приложении.js
//= require jquery_ujs
Я заменил его и его рабочих..
======= обновлено =========
после 5 лет, я вернулся с той же ошибкой, теперь у меня есть новый рельсы 5.1.6, и я снова нашел этот пост. Так же, как Круг жизни.
Теперь в чем была проблема: рельсы 5.1 удалена поддержка jquery и jquery_ujs по умолчанию, и добавил
//= require rails-ujs in application.js
Он делает следующие вещи:
- диалоги подтверждения силы для различных действий;
- сделать не получить запросы от гиперссылок;
- сделать формы или гиперссылки отправлять данные асинхронно с Ajax;
- кнопки отправки автоматически отключаются при отправке формы, чтобы предотвратить двойной щелчок. (от: https://github.com/rails/rails-ujs/tree/master)
но почему он не включает токен csrf для запроса ajax? Если кто-нибудь знает об этом подробно в комментарии мне. Я ценю это.
В любом случае я добавил следующее в свой пользовательский js-файл, чтобы заставить его работать (Спасибо за другие ответы, которые помогут мне достичь этого кода):
$( document ).ready(function() { $.ajaxSetup({ headers: { 'X-CSRF-Token': Rails.csrfToken() } }); ---- ---- });
Если вы используете javascript с jQuery для создания токена в своей форме, это работает:
<input name="authenticity_token" type="hidden" value="<%= $('meta[name=csrf-token]').attr('content') %>" />
очевидно, вам нужно иметь
<%= csrf_meta_tag %>
в вашем макете Ruby.
Если вы не используете jQuery и используя что-то вроде fetch API для запросов вы можете использовать следующее, чтобы получить
csrf-token
:
document.querySelector('meta[name="csrf-token"]').getAttribute('content')
fetch('/users', { method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', 'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').getAttribute('content')}, credentials: 'same-origin', body: JSON.stringify( { id: 1, name: 'some user' } ) }) .then(function(data) { console.log('request succeeded with JSON response', data) }).catch(function(error) { console.log('request failed', error) })
используйте jquery.csrf (https://github.com/swordray/jquery.csrf).
рельсы 5.1 или более поздней
$ yarn add jquery.csrf
//= require jquery.csrf
рельсы 5.0 или перед
source 'https://rails-assets.org' do gem 'rails-assets-jquery.csrf' end
//= require jquery.csrf
исходный код
(function($) { $(document).ajaxSend(function(e, xhr, options) { var token = $('meta[name="csrf-token"]').attr('content'); if (token) xhr.setRequestHeader('X-CSRF-Token', token); }); })(jQuery);
для тех из вас, кто нуждается в ответе не jQuery, вы можете просто добавить следующее:
xmlhttp.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'));очень простой пример можно найти здесь:
xmlhttp.open("POST","example.html",true); xmlhttp.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content')); xmlhttp.send();
Если кому-то нужна помощь, связанная с Uploadify и Rails 3.2 (например, когда я гуглил этот пост), этот пример приложения может быть полезен: https://github.com/n0ne/Uploadify-Carrierwave-Rails-3.2.3/blob/master/app/views/pictures/index.html.erb
также проверьте решение контроллера в этом приложении
Я использую рельсы 4.2.4 и не мог понять, почему я получаю:
Can't verify CSRF token authenticity
у меня в макете:
<%= csrf_meta_tags %>
в контроллере:
protect_from_forgery with: :exception
вызов
tcpdump -A -s 999 -i lo port 3000
показывал заголовок устанавливается ( несмотря на то, что не нужно устанавливать заголовки сajaxSetup
- это уже было сделано):X-CSRF-Token: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX Content-Type: application/x-www-form-urlencoded; charset=UTF-8 X-Requested-With: XMLHttpRequest DNT: 1 Content-Length: 125 authenticity_token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
в конце концов это не удалось, потому что у меня были куки выключены. CSRF не работает без включения cookies, так что это еще одна возможная причина если вы видите эту ошибку.
Я боролся с этой проблемой несколько дней. Любой вызов GET работал правильно, но все PUTs генерировали бы ошибку "не удается проверить подлинность токена CSRF". Мой сайт работал нормально, пока я не добавил сертификат SSL в nginx.
Я, наконец, наткнулся на эту недостающую строку в моих настройках nginx:
location @puma { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; proxy_set_header X-Forwarded-Proto https; # Needed to avoid 'WARNING: Can't verify CSRF token authenticity' proxy_pass http://puma; }
после добавления недостающей строки "proxy_set_header X-Forwarded-Proto https;" все мои ошибки токена CSRF завершаются.
надеюсь, это поможет кому-то еще, кто также бьется головой о стену. хаха