2015-02-09 6 views
17

मैं लैरवेल 5 ऐप पर काम कर रहा हूं जिसमें सभी POST अनुरोधों के लिए डिफ़ॉल्ट रूप से सीएसआरएफ सुरक्षा सक्षम है। मुझे यह अतिरिक्त सुरक्षा पसंद है इसलिए मैं इसके साथ काम करने की कोशिश कर रहा हूं।

एक साधारण $.post() अनुरोध करते समय मुझे 'Illuminate\Session\TokenMismatchException' त्रुटि मिली क्योंकि आवश्यक फॉर्म इनपुट _token पोस्ट डेटा से गायब था।

var userID = $("#userID").val(); 
$.post('/admin/users/delete-user', {id:userID}, function() { 
// User deleted 
}); 

मैं अपने CSRF टोकन मेरी शीर्षक में एक मेटा क्षेत्र के रूप में जमा है और आसानी से उपयोग कर इसे उपयोग कर सकते हैं:

var csrf_token = $('meta[name="csrf-token"]').attr('content'); 

क्या यह संभव है यहाँ सवाल में एक $ .post अनुरोध का एक उदाहरण है सभी आउटगोइंग $.post() अनुरोधों पर जेसन डेटा में इसे जोड़ने के लिए? मैं हेडर का उपयोग करके की कोशिश की लेकिन Laravel उन्हें पहचान नहीं लगता था -

var csrf_token = $('meta[name="csrf-token"]').attr('content'); 
alert(csrf_token); 
$.ajaxPrefilter(function(options, originalOptions, jqXHR){ 
    if (options['type'].toLowerCase() === "post") { 
     jqXHR.setRequestHeader('X-CSRFToken', csrf_token); 
    } 
}); 
+0

मैं सही ढंग से समझते हो कि आप अपने डेटा वस्तु बनाना चाहते एक '_token' क्षेत्र है? (उदाहरण के लिए, 'विकल्प [' डेटा '] ._ token = csrf_token' जैसे कुछ?) यदि आपके पास कोई है तो एक कार्य अनुरोध का एक उदाहरण उपयोगी होगा। – apsillers

+0

हां, बिल्कुल ... – NightMICU

+0

अनुरोध कार्य करने के लिए मुझे सीधे पोस्ट डेटा पर टोकन जोड़ना होगा - इसलिए '{id: userID, '_token': टोकन}' – NightMICU

उत्तर

21

आपका $.ajaxPrefilter दृष्टिकोण एक अच्छा एक है। आपको हेडर जोड़ने की आवश्यकता नहीं है, हालांकि; आपको बस data स्ट्रिंग में एक संपत्ति जोड़ने की आवश्यकता है।

डाटा $.post से पीछे तर्क के रूप में प्रदान की जाती है, और फिर एक क्वेरी स्ट्रिंग (id=foo&bar=baz&...) prefilter से पहले data विकल्प के लिए उपयोग हो जाता है के रूप में स्वरूपित। इस प्रकार, आप क्वेरी स्ट्रिंग के लिए अपने स्वयं के क्षेत्र को जोड़ने की आवश्यकता:

var csrf_token = $('meta[name="csrf-token"]').attr('content'); 
$.ajaxPrefilter(function(options, originalOptions, jqXHR){ 
    if (options.type.toLowerCase() === "post") { 
     // initialize `data` to empty string if it does not exist 
     options.data = options.data || ""; 

     // add leading ampersand if `data` is non-empty 
     options.data += options.data?"&":""; 

     // add _token entry 
     options.data += "_token=" + encodeURIComponent(csrf_token); 
    } 
}); 

यह id=userID&_token=csrf_token में id=userID हो जाएगा।

+0

ठीक है, मैं केवल इस विकल्प को 'विकल्प [' डेटा '] = विकल्प [' डेटा '] +' और _token = '+ csrf_token;' के साथ प्राप्त कर सकता हूं - डॉट नोटेशन काम नहीं कर रहा है। यह बेहतर दिखता है, कोई विचार क्या समस्या हो सकती है? – NightMICU

+0

@NightMICU मैं देखता हूं; समस्या डॉट नोटेशन के साथ नहीं है, बल्कि यह कि jQuery प्रीफ़िल्टर इसे प्राप्त करने से पहले डेटा ऑब्जेक्ट को क्वेरी स्ट्रिंग में बदल देता है। मैंने संपादित किया है (लेकिन मैंने परीक्षण नहीं किया है, इसलिए अगर यह अभी भी टूट जाए तो मुझे बताएं)। – apsillers

+0

अच्छा लग रहा है! बहुत बहुत धन्यवाद! – NightMICU

0

मुझे लगता है कि उपर्युक्त समाधान भी काम नहीं कर सकता है। जब आप ऐसा करेंगे:

var x; 
x + "" 
// "undefined" + empty string coerces value to string 

आप की तरह "undefined_token = xxx" डेटा मिलेगा

आप laravel के लिए ऊपर समाधान का उपयोग करते हैं, उदाहरण के लिए हटाना आप इस तरह की जाँच करने के लिए है:

if (typeof options.data === "undefined") 
    options.data = ""; 
else 
    options.data += "&"; 
options.data = "_token=" + csrf_token; 
12

लैरवेल दस्तावेज से:

उदाहरण के लिए, आप "मेटा" टैग में टोकन स्टोर कर सकते हैं:

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

$ .ajaxSetup ({ हेडर:: { 'एक्स-CSRF-टोकन': $ ('मेटा [नाम = "CSRF-टोकन"]' यह सरल, अपने AJAX आधारित अनुप्रयोगों के लिए सुविधाजनक CSRF सुरक्षा प्रदान करता है) .attr ('सामग्री') }});

तो उदाहरण के लिए आप नीचे जैसा अनुरोध कर सकते हैं।

आपके विचार पर इस मेटा टैग जोड़ें: जब आप आईडी = "कुछ-आईडी" वाले एक तत्व क्लिक

<meta name="csrf-token" content="{{ csrf_token() }}"> 

और यह एक उदाहरण स्क्रिप्ट जो आप Laravel साथ संवाद कर सकते है (अनुरोध भेजता है और आप कर सकते हैं id = "परिणाम" वाले एक तत्व में प्रतिक्रिया देखें):

<script type="text/javascript"> 
    $(document).ready(function(){ 

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

     $("#some-id").on("click", function() { 
      var request; 


      request = $.ajax({ 
       url: "/your/url", 
       method: "POST", 
       data: 
       { 
        a: 'something', 
        b: 'something else', 
       }, 
       datatype: "json" 
      }); 

      request.done(function(msg) { 
       $("#result").html(msg); 
      }); 

      request.fail(function(jqXHR, textStatus) { 
       $("#result").html("Request failed: " + textStatus); 
      }); 
     }); 

    }); 
</script> 
4

आम तौर पर मैं अवधारणा कोर्नेल एक बात को छोड़कर सुझाव से सहमत हैं।

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

बाद के सभी अजाक्स किसी भी समारोह का उपयोग कर जब तक अलग-अलग कॉल द्वारा ओवरराइड, नई सेटिंग्स का उपयोग करेगा, $ .ajaxSetup() की

अगले मंगलाचरण जब तक कॉल यदि आप $.ajax() का उपयोग करते हैं, तो data संपत्ति या headers का उपयोग करना अधिक सुविधाजनक है। लार्वेल सीएसआरएफ-टोकन को अनुरोध पैरामीटर या हेडर दोनों के रूप में अनुमति देता है।

सबसे पहले, आप दृश्य में निम्न मेटा टैग को जोड़ने के

<meta name="csrf-token" content="{{ csrf_token() }}"> 

और फिर एक ajax अनुरोध या तो रास्ता बनाना:

$.ajax({ 
    url: "/your/url", 
    method: "POST", 
    data: 
    { 
     a: 'something', 
     b: 'something else', 
     _token: $('meta[name="csrf-token"]').attr('content') 
    }, 
    datatype: "json" 
}); 

या

$.ajax({ 
    url: "/your/url", 
    method: "POST", 
    data: 
    { 
     a: 'something', 
     b: 'something else', 
    }, 
    headers: 
    { 
     'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') 
    } 
    datatype: "json" 
}); 
0

Django documentation on CSRF एक देता है उचित शीर्षलेख जोड़ने के लिए ajaxSetup के साथ अच्छा कोड स्निपेट सभी अनुरोध प्रकार जहां यह मायने रखती है:

function csrfSafeMethod(method) { 
    // these HTTP methods do not require CSRF protection 
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); 
} 
$.ajaxSetup({ 
    beforeSend: function(xhr, settings) { 
     if (!csrfSafeMethod(settings.type) && !this.crossDomain) { 
      xhr.setRequestHeader("X-CSRFToken", csrftoken); 
     } 
    } 
}); 
संबंधित मुद्दे