UYARI: CSRF jetonu kimlik doğrulama rayları doğrulanamıyor


238

AJAX ile denetleyiciye görünümden veri gönderiyorum ve bu hatayı aldım:

UYARI: CSRF jetonu doğruluğu doğrulanamıyor

Sanırım bu jetonu veri ile göndermek zorundayım.

Bunu nasıl yapabileceğimi bilen var mı?

Edit: Benim çözümüm

AJAX yazı içine aşağıdaki kodu koyarak bunu yaptım:

headers: {
  'X-Transaction': 'POST Example',
  'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
},

7
Eğer var <csrf_meta_tag% =%> düzeninizin başlığındaki?
Anatoly

evet böyle: <% = csrf_meta_tags%>
kbaccouche

6
Eğer var jquery-raylar ajax istemci tarafında işlevsellik sağlamak kütüphaneleri?
Anatoly

2
Ve HAML yolu "= csrf_meta_tags" eklemektir
Ege Akpınar

güzel soru, sorduğunuz için teşekkürler
AMIC MING

Yanıtlar:


374

Bunu yapmalısın:

  1. <%= csrf_meta_tag %>Düzeninizde olduğundan emin olun

  2. beforeSendBaşlığı aşağıdaki gibi ayarlamak için tüm ajax isteğine ekleyin :


$.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);
  }
});

Tüm isteklerde jeton göndermek için şunları kullanabilirsiniz:

$.ajaxSetup({
  headers: {
    'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
  }
});

5
Teşekkürler! Benim için bir cazibe gibi çalıştı!
Misha Moroshko

35
Rails ekibi tarafından sağlanan jQuery UJS kütüphanesi, CSRF jetonunu jQuery AJAX isteğine otomatik olarak ekler. README kurulumun nasıl yapılacağına ilişkin talimatlar içerir. github.com/rails/jquery-ujs/blob/master/src/rails.js#L91
James Conroy-Finn

1
$ .AjaxSetup işleviyle tüm isteklerin üstbilgisini aynı anda ayarlayabileceğinizi unutmayın.
Pieter Jongsma

1
Mükemmel! Bu cevabı bir süredir arıyoruz. Sorunsuz çalışır. Teşekkürler!
cassi.lup

4
Not olarak, yukarıda önerildiği gibi jQuery UJS kullanıyorsanız, rails-ujs include'un jquery içerdikten sonra geldiğinden emin olmanız gerekir veya op ile aynı hatayla başarısız olur.
Topher Fangio

31

Bunu yapmanın en iyi yolu <%= form_authenticity_token.to_s %>, jetonu doğrudan ray kodunuzda yazdırmak için kullanmaktır . Diğer mesajlarda bahsedildiği gibi csrf jetonu dom aramak için javascript kullanmanız gerekmez. başlıklar seçeneğini aşağıdaki gibi eklemeniz yeterlidir;

$.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) %>"
})

7
Bunun yerine, her ajax komut için bunu yapmanın, eklemek olabilir başlıkları için $ .ajaxSetup () .
Scott McMillin

1
Bu yanıtı kullanmanızı tavsiye ederim ...
Opsidao

14
Javascript ERB kullanma yaklaşımını gerçekten sevmiyorum.
radixhound

Bu, javascriptinizi çok kısıtlayıcı olan ERB ile oluşturmaya zorlar. ERB'nin uygun olabileceği yerler olsa bile, olmadığı yerlerde başkaları da vardır ve sadece jetonu almak için eklemek bir atık olacaktır.
sockmonk

22

Doğru hatırlıyorsam, bu sorundan kurtulmak için formunuza aşağıdaki kodu eklemeniz gerekir:

<%= token_tag(nil) %>

Parametreyi unutmayın.


8
Aslında bu şekilde olmalıdır: <%= token_tag(nil) %>. Sonra otomatik olarak oluşturulan jetonu alırsınız.
szeryf

15

Gerçekten de en basit yol. Üstbilgileri değiştirmekle uğraşmayın.

Sahip olduğundan emin ol:

<%= csrf_meta_tag %> in your layouts/application.html.erb

Sadece gizli bir giriş alanı şöyle yapın:

<input name="authenticity_token" 
               type="hidden" 
               value="<%= form_authenticity_token %>"/>

Veya bir jQuery ajax yayını istiyorsanız:

$.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);
    }
});

Gizli giriş alanını giriş formuma eklemek benim için sorunu çözdü.
Teemu Leisti

Rails form yardımcılarını kullanırsanız bu otomatik olarak yapılır.
Jason FB

13

Eski bir uygulamadan, csrf meta etiketi de dahil olmak üzere raylar 3.1'e geçiş hala çözülmüyor. Rubyonrails.org blogunda, bazı yükseltme ipuçları veriyorlar ve özellikle düzeninizin baş bölümüne gitmesi gereken bu jquery hattı:

$(document).ajaxSend(function(e, xhr, options) {
 var token = $("meta[name='csrf-token']").attr("content");
  xhr.setRequestHeader("X-CSRF-Token", token);
});

bu blog yazısından alınmıştır: http://weblog.rubyonrails.org/2011/2/8/csrf-protection-bypass-in-ruby-on-rails .

Benim durumumda, oturum her ajax isteği üzerine sıfırlanıyordu. Yukarıdaki kodu eklemek bu sorunu çözdü.


10
  1. <%= csrf_meta_tag %>Düzeninizde olduğundan emin olun
  2. beforeSendBaşlığı ayarlamak için ajax isteğine csrf belirtecini eklemek için a ekleyin . Bu yalnızca postistekler için gereklidir .

Csrf-token'ı okumak için kod şu şekilde mevcuttur rails/jquery-ujs:

$.ajax({
  url: url,
  method: 'post',
  beforeSend: $.rails.CSRFProtection,
  data: {
    // ...
  }
})

Rails zaten dahil olanları yeniden uygulamadan basit. Bu seçilen cevap olmalıdır.
jiehanzheng

In Rails 5.1 ayrıca çalışıyor:headers: { 'X-CSRF-Token': Rails.csrfToken() }
olhor

@nathanvda, Belki bu benzer soruya cevap verebilirsiniz: stackoverflow.com/questions/50159847/…


6

Burada en çok oy alan cevaplar doğrudur, ancak jQuery'ye oturum çerezini geçmesini açıkça söylemediğiniz sürece oturum kullanılamayacağı için alanlar arası istekleri gerçekleştiriyorsanız çalışmaz . Bunu nasıl yapacağınız aşağıda açıklanmıştır:

$.ajax({ 
  url: url,
  type: 'POST',
  beforeSend: function(xhr) {
    xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))
  },
  xhrFields: {
    withCredentials: true
  }
});

Bu çok benzer soruyu cevaplayıp yanıtlayamayacağınızı sorabilir miyim? stackoverflow.com/questions/50159847/…

5

Aşağıdaki gibi küresel olarak yazabilirsiniz.

Normal 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'))}
    });
});

Kahve Senaryosu:

  $('#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'))
  }

5

ayy ..

Benim application.js aşağıdaki satırı kaçırdım

//= require jquery_ujs

Ben onun yerini ve onun çalışma ..

======= GÜNCELLENDİ =========

5 yıl sonra, Same error ile geri döndüm, şimdi yeni Rails 5.1.6'm var ve bu yazıyı tekrar buldum. Tıpkı yaşam döngüsü gibi.

Şimdi sorun şuydu: Rails 5.1 varsayılan olarak jquery ve jquery_ujs desteğini kaldırdı ve eklendi

//= require rails-ujs in application.js

Aşağıdakileri yapar:

  1. çeşitli eylemler için onay iletişim kutularını zorla;
  2. köprülerden GET dışı istekler yapmak;
  3. Formların veya köprülerin Ajax ile veri zaman uyumsuz olarak gönderilmesini sağlama;
  4. çift ​​tıklamayı önlemek için form gönderme sırasında gönderme düğmelerinin otomatik olarak devre dışı bırakılmasını sağlayın. ( https://github.com/rails/rails-ujs/tree/master adresinden )

Ama neden ajax isteği için csrf jetonunu içermiyor? Herkes bu konuda ayrıntılı bilmek sadece bana yorum. Bunu takdir ediyorum.

Her neyse, çalışması için özel js dosyama aşağıdakileri ekledim (Bu koda ulaşmama yardımcı olacak diğer cevaplar için teşekkürler):

$( document ).ready(function() {
  $.ajaxSetup({
    headers: {
      'X-CSRF-Token': Rails.csrfToken()
    }
  });
  ----
  ----
});

Benim de yapmam gereken buydu. Bunun ortaya çıkmasının nedeni, mevcut bir Rails Uygulamasını yavaşça değiştirmek için bir React Uygulaması oluşturmamdır. Mevcut uygulamada bir sürü javascript gürültüsü olduğundan, farklı bir javascript dosyasına erişen farklı bir düzen oluşturdum, ancak ekleyemedim jquery_ujs. Hüner buydu.
Wylliam Judd

1
Evet, Bazen Yeniden işlerken bir şeyleri gözden kaçırırsak, bir şeyleri yeniden düzenleriz ... Neyin yanlış gittiğini bulmak zor. Çalıştırmak için el ile hiçbir şey yapmadığımızdan, Rails otomatik olarak dahil. Zaten orada olduğunu düşünüyoruz. Böyle sosyal Qn / Ans Siteleri için teşekkürler
Abhi

Belki bu benzer soruya cevap verebilirsiniz: stackoverflow.com/questions/50159847/…

4

JQuery kullanmıyorsanız ve istekler için API getirme gibi bir şey kullanmıyorsanız aşağıdakileri elde etmek için aşağıdakileri kullanabilirsiniz 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)
    })

Bu çok benzer soruyu cevaplayıp yanıtlayamayacağınızı sorabilir miyim? stackoverflow.com/questions/50159847/…

4

Jquery.csrf ( https://github.com/swordray/jquery.csrf ) kullanın .

  • Raylar 5.1 veya üstü

    $ yarn add jquery.csrf
    //= require jquery.csrf
  • Raylar 5.0 veya öncesi

    source 'https://rails-assets.org' do
      gem 'rails-assets-jquery.csrf'
    end
    //= require jquery.csrf
  • Kaynak kodu

    (function($) {
      $(document).ajaxSend(function(e, xhr, options) {
        var token = $('meta[name="csrf-token"]').attr('content');
        if (token) xhr.setRequestHeader('X-CSRF-Token', token);
      });
    })(jQuery);


5.1 web paketini kullanırken //= require jquery.csrfişe yaramıyor değil mi? Bunun yerine içinde paketi js dosyası kullandım import 'jquery.csrf'. Bunu görünümlerinize bir paket etiketi eklemenize gerek olmadığını unutmayın .
Damien Justin Šutevski

3

Formunuzda jeton oluşturmak için jQuery ile javascript kullanıyorsanız, bu çalışır:

<input name="authenticity_token" 
       type="hidden" 
       value="<%= $('meta[name=csrf-token]').attr('content') %>" />

Açıkçası, <%= csrf_meta_tag %>Ruby düzeninizde olması gerekir .


2

Olmayan bir jQuery cevap ihtiyacı olanlar için basit aşağıdakileri ekleyebilirsiniz:

xmlhttp.setRequestHeader ('X-CSRF-Token', $ ('meta [ad = "csrf-token"]'). attr ('içerik'));

Çok basit bir örnek burada olabilir:

xmlhttp.open ( "POST", "example.html", true);
xmlhttp.setRequestHeader ('X-CSRF-Token', $ ('meta [ad = "csrf-token"]'). attr ('içerik'));
xmlhttp.send ();

6
Bu, seçiciler için jQuery kullanmıyor mu?
Yule

2

Günlerce bu sorunla mücadele ettim. Herhangi bir GET çağrısı düzgün çalışıyordu, ancak tüm PUT'lar "CSRF jetonu kimlik doğrulaması doğrulanamıyor" hatası oluşturur. Web sitem, nginx'e bir SSL sertifikası ekleyene kadar iyi çalışıyordu.

Sonunda nginx ayarlarımda bu eksik hatta tökezledim:

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; 
}

Eksik "proxy_set_header X-Forwarded-Proto https;" satırını ekledikten sonra, tüm CSRF jeton hatalarım kesiliyor.

Umarım bu da başlarını duvara dayayan bir başkasına yardım eder. haha



0

Rails 4.2.4 kullanıyorum ve neden aldığımı çözemedim:

Can't verify CSRF token authenticity

Ben düzeni var:

<%= csrf_meta_tags %>

Denetleyicide:

protect_from_forgery with: :exception

Çağırma tcpdump -A -s 999 -i lo port 3000, ayarlanan üstbilgiyi gösteriyordu (üstbilgileri ayarlamanız gerekmese de ajaxSetup- zaten yapıldı):

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

Sonunda başarısız oldu çünkü çerezleri kapalı vardı. CSRF, çerezler etkinleştirilmeden çalışmaz, bu nedenle bu hatayı görüyorsanız başka bir olası nedendir.


çok yardımsever!
joehwang
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.