चेतावनी: CSRF टोकन प्रामाणिकता रेल को सत्यापित नहीं कर सकता


238

मैं AJAXand के साथ कंट्रोलर को देखने के लिए डेटा भेज रहा हूँ मुझे यह त्रुटि मिली:

चेतावनी: CSRF टोकन प्रामाणिकता सत्यापित नहीं कर सकता

मुझे लगता है कि मुझे यह टोकन डेटा के साथ भेजना है।

क्या किसी को पता है कि मैं यह कैसे कर सकता हूं?

संपादित करें: मेरा समाधान

मैंने AJAX पोस्ट के अंदर निम्नलिखित कोड डालकर ऐसा किया:

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

7
क्या आपके लेआउट हेडर में <% = csrf_meta_tag%> है?
अनातोली

इस तरह से हाँ: <% = csrf_meta_tags%>
kbaccouche

6
क्या आपके पास jquery-rails पुस्तकालय हैं जो ajax क्लाइंट-साइड कार्यक्षमता प्रदान करते हैं?
अनातोली

2
और HAML रास्ता "= csrf_meta_tags" जोड़ना है
Ege Akpinar

अच्छा सवाल, पूछने के लिए धन्यवाद
AMIC MING

जवाबों:


374

तुम्हें यह करना चाहिए:

  1. सुनिश्चित करें कि आप <%= csrf_meta_tag %>अपने लेआउट में हैं

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

5
धन्यवाद! मेरे लिए एक आकर्षण की तरह काम किया!
मीशा मोरोशो

35
रेल टीम द्वारा उपलब्ध कराई गई jQuery UJS लाइब्रेरी CSRF टोकन को स्वचालित रूप से jQuery AJAX अनुरोध में जोड़ती है। README में सेटअप प्राप्त करने के बारे में निर्देश हैं। github.com/rails/jquery-ujs/blob/master/src/rails.js#L91
जेम्स कॉनरॉय-फिन

1
ध्यान दें कि आप $ .ajaxSetup फ़ंक्शन के साथ एक बार में सभी अनुरोधों के लिए हेडर सेट कर सकते हैं।
पीटर जोंगस्मा

1
अति उत्कृष्ट! इस उत्तर के लिए कुछ समय के लिए खोज रहा है। निर्बाध रूप से काम करता है। धन्यवाद!
cassi.lup

4
एक नोट के रूप में, यदि आप ऊपर दिए गए सुझाव के अनुसार jQuery UJS का उपयोग कर रहे हैं, तो आपको यह सुनिश्चित करने की आवश्यकता है कि रेल में शामिल होने के बाद रेल-उजे शामिल हैं या यह ऑप के समान त्रुटि के साथ विफल हो जाएगा।
Topher Fangio

31

ऐसा करने का सबसे अच्छा तरीका यह है <%= form_authenticity_token.to_s %>कि आप सीधे टोकन का प्रिंट आउट अपने रेल कोड में इस्तेमाल करें। आपको अन्य पोस्ट्स के रूप में सीएसआरएफ टोकन के लिए डोम की खोज करने के लिए जावास्क्रिप्ट का उपयोग करने की आवश्यकता नहीं है। बस नीचे दिए गए हेडर विकल्प जोड़ें;

$.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
इसके बजाय प्रत्येक ajax आदेश के लिए ऐसा करने का, आप जोड़ सकते हेडर के लिए $ .ajaxSetup ()
स्कॉट मैकमिलिन

1
मैं इस जवाब का उपयोग करने की सलाह देता हूं ...
opsidao

14
मुझे वास्तव में जावास्क्रिप्ट में ईआरबी का उपयोग करने का दृष्टिकोण पसंद नहीं है।
मूलांक

यह आपको ईआरबी के साथ अपनी जावास्क्रिप्ट बनाने के लिए मजबूर करता है, जो बहुत सीमित है। यहां तक ​​कि अगर ऐसे स्थान हैं जहां ईआरबी एक अच्छा फिट हो सकता है, तो कुछ अन्य हैं जहां यह नहीं है, और इसे सिर्फ टोकन प्राप्त करने के लिए जोड़ना एक बेकार होगा।
sockmonk

22

यदि मुझे सही याद है, तो आपको इस समस्या से छुटकारा पाने के लिए, निम्न कोड को अपने फॉर्म में जोड़ना होगा:

<%= token_tag(nil) %>

पैरामीटर मत भूलना।


8
वास्तव में, यह होना चाहिए <%= token_tag(nil) %>:। फिर आपको ऑटो जनरेट टोकन मिलता है।
szeryf

15

वास्तव में सबसे सरल तरीका है। हेडर बदलने के साथ परेशान मत करो।

आप सुनिश्चित करें कि आपके पास:

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

बस एक छिपे हुए इनपुट क्षेत्र को ऐसा करें:

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

या यदि आप एक jQuery के अजाक्स पोस्ट चाहते हैं:

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

मेरे इनपुट फॉर्म में छिपे इनपुट फ़ील्ड को जोड़ने से मेरे लिए समस्या हल हो गई।
तेमू लीस्टी

यह स्वचालित रूप से किया जाता है यदि आप रेल के रूप सहायकों का उपयोग करते हैं।
जेसन FB

13

Csrf मेटा टैग सहित एक पुराने ऐप से 3.1 तक रेल को अपग्रेड करना अभी भी इसे हल नहीं कर रहा है। Rubyonrails.org ब्लॉग पर, वे कुछ अपग्रेड युक्तियां देते हैं, और विशेष रूप से jquery की यह पंक्ति जो आपके लेआउट के मुख्य भाग में जानी चाहिए:

$(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

मेरे मामले में, प्रत्येक अजाक्स अनुरोध पर सत्र को रीसेट किया जा रहा था। उपरोक्त कोड जोड़ने से वह समस्या हल हो गई।


10
  1. सुनिश्चित करें कि आप <%= csrf_meta_tag %>अपने लेआउट में हैं
  2. beforeSendहेडर सेट करने के लिए ajax अनुरोध में csrf-token को शामिल करने के लिए a जोड़ें । यह केवल postअनुरोधों के लिए आवश्यक है ।

सीएसआरएफ-टोकन को पढ़ने के लिए कोड उपलब्ध है rails/jquery-ujs, इसलिए यह केवल इस प्रकार उपयोग करना आसान है, इस प्रकार है:

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

री-इम्प्लीमेंट के बिना सरल, जो पहले से ही रेल द्वारा शामिल किया गया है। यह चयनित उत्तर होना चाहिए।
जीशानजेंग

रेल में 5.1 भी काम करता है:headers: { 'X-CSRF-Token': Rails.csrfToken() }
ओल्होर

@nathanvda, शायद आप इस तरह के प्रश्न का उत्तर दे सकते हैं: stackoverflow.com/questions/50159847/…


6

यहां शीर्ष वोट किए गए उत्तर सही हैं, लेकिन यदि आप क्रॉस-डोमेन अनुरोध कर रहे हैं तो काम नहीं करेगा क्योंकि सत्र उपलब्ध नहीं होगा जब तक कि आप स्पष्ट रूप से jQuery को सत्र कुकी पास करने के लिए नहीं कहेंगे। यहाँ है कि कैसे करना है:

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

क्या मैं आपसे पूछ सकता हूं कि क्या आप इसी तरह के सवाल का जवाब दे सकते हैं? stackoverflow.com/questions/50159847/…

5

आप इसे नीचे की तरह विश्व स्तर पर लिख सकते हैं।

सामान्य 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'))
  }

5

उफ़ ..

मुझे अपने आवेदन में निम्नलिखित पंक्ति याद आई। js

//= require jquery_ujs

मैंने इसे और इसके काम को बदल दिया।

======= अद्यतन किया गया =========

5 वर्षों के बाद, मैं उसी त्रुटि के साथ वापस आ गया हूं, अब मेरे पास बिल्कुल नई रेल 5.1.6 है , और मुझे यह पद फिर से मिला। जैसे जीवन का चक्र।

अब मुद्दा क्या था: रेल 5.1 डिफ़ॉल्ट रूप से jquery और jquery_ujs के लिए समर्थन हटा दिया , और जोड़ा गया

//= require rails-ujs in application.js

यह निम्नलिखित बातें करता है:

  1. विभिन्न क्रियाओं के लिए बल पुष्टि संवाद;
  2. हाइपरलिंक से गैर-जीईटी अनुरोध करें;
  3. प्रपत्र या हाइपरलिंक Ajax के साथ अतुल्यकालिक रूप से डेटा जमा करना;
  4. सबमिट बटन डबल-क्लिक को रोकने के लिए फ़ॉर्म सबमिट पर स्वचालित रूप से अक्षम हो जाते हैं। (से: https://github.com/rails/rails-ujs/tree/master )

लेकिन यह अजाक्स अनुरोध के लिए सीएसआरएफ टोकन सहित क्यों नहीं है? अगर किसी को इस बारे में विस्तार से पता है तो मुझे कमेंट करें। मैं सराहना करता हूँ।

वैसे भी मैंने इसे बनाने के लिए अपने कस्टम js फ़ाइल में निम्नलिखित जोड़ा है (इस कोड तक पहुँचने में मेरी मदद करने के लिए अन्य उत्तर के लिए धन्यवाद):

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

यही मुझे भी करने की जरूरत थी। इसका कारण यह है क्योंकि मैं एक मौजूदा ऐप को धीरे-धीरे बदलने के लिए एक रिएक्ट ऐप बना रहा हूं। चूंकि मौजूदा ऐप में जावास्क्रिप्ट शोर का एक समूह चल रहा है, मैंने एक अलग लेआउट बनाया, जो एक अलग जावास्क्रिप्ट फ़ाइल तक पहुंचता है, लेकिन मैं शामिल करने में विफल रहा jquery_ujs। यही चाल थी।
व्यालियम जुड

1
हाँ, कभी-कभी अगर हम याद करते हैं कि जब फिर से काम करते हैं, तो कुछ रिफलेक्टर करते हैं। मुझे लगता है कि क्या गलत हो रहा है। क्योंकि हम इसे काम करने के लिए मैन्युअल रूप से कुछ नहीं कर रहे हैं, रेल स्वचालित रूप से इसमें शामिल है। हमें लगता है कि यह पहले से ही वहां है। ऐसे सामाजिक Qn / Ans साइट्स के लिए धन्यवाद
Abhi

शायद आप इस तरह के सवाल का जवाब दे सकते हैं: stackoverflow.com/questions/50159847/…

4

यदि आप 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)
    })

क्या मैं आपसे पूछ सकता हूं कि क्या आप इसी तरह के सवाल का जवाब दे सकते हैं? stackoverflow.com/questions/50159847/…

4

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


5.1 वेबपैक का उपयोग //= require jquery.csrfकरते हुए, सही काम नहीं कर रहा है? इसके बजाय मैंने इसके साथ पैक js फ़ाइल का उपयोग किया import 'jquery.csrf'। ध्यान दें कि आपको अपने विचारों में पैक टैग के साथ इसे शामिल करने की आवश्यकता नहीं है।
डेमियन जस्टिन v्यूटेवस्की

3

यदि आप अपने फॉर्म में टोकन जेनरेट करने के लिए jQuery के साथ जावास्क्रिप्ट का उपयोग कर रहे हैं, तो यह काम करता है:

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

जाहिर है, आपको <%= csrf_meta_tag %>अपने रूबी लेआउट में होना चाहिए।


2

उन लोगों के लिए जिन्हें एक गैर jQuery उत्तर की आवश्यकता है, आप निम्नलिखित को जोड़ सकते हैं:

xmlhttp.setRequestHeader ('X-CSRF-Token', $ ('मेटा [नाम = "csrf-token"]))। attr (' सामग्री '));

एक बहुत ही सरल उदाहरण यहाँ सेन हो सकता है:

xmlhttp.open ( "पोस्ट", "example.html", true);
xmlhttp.setRequestHeader ('X-CSRF-Token', $ ('मेटा [नाम = "csrf-token"]))। attr (' सामग्री '));
xmlhttp.send ();

6
क्या यह चयनकर्ताओं के लिए jQuery का उपयोग नहीं करता है?
यूल

2

मैं इस मुद्दे से कई दिनों तक जूझता रहा। कोई भी GET कॉल सही तरीके से काम कर रहा था, लेकिन सभी PUTs "CSRF टोकन प्रामाणिकता को सत्यापित नहीं कर सकते" त्रुटि उत्पन्न करेगा। मेरी वेबसाइट तब तक ठीक काम कर रही थी जब तक कि मैंने nginx में एक SSL प्रमाणपत्र नहीं जोड़ा था।

मैं आखिरकार अपनी 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; 
}

लापता लाइन "प्रॉक्सी_सेट_हीडर एक्स-फ़ॉर्वर्ड-प्रोटो https;" को जोड़ने के बाद, मेरे सभी सीएसआरएफ टोकन त्रुटियां छोड़ देते हैं।

उम्मीद है कि यह किसी और की मदद करता है जो एक दीवार के खिलाफ भी अपना सिर पीट रहा है। haha


1

अगर किसी को Uploadify और Rails 3.2 से संबंधित मदद चाहिए (जैसे कि जब मैंने इस पोस्ट को googled किया), तो यह नमूना ऐप मददगार हो सकता है: https://github.com/n0ne/Uploadify-Carrierwave-Rails-3.2.3-blob/master /app/views/pictures/index.html.erb

इस ऐप में कंट्रोलर सॉल्यूशन भी देखें


0

मैं ४.२.४ का उपयोग कर रहा हूं और काम नहीं कर पा रहा हूं, इसलिए मुझे मिल रहा है:

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 कुकीज़ के बिना काम नहीं करता है, इसलिए यदि आप इस त्रुटि को देख रहे हैं तो यह एक और संभावित कारण है।


यह बहुत उपयोगी है!
जोहांग
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.