2009-08-07 14 views
14

किसी कारण से मुझे जेसन या एक्सएमएल का उपयोग करते समय मेरे आवेदन में पोस्ट अनुरोध करते समय अमान्य प्रमाणीकरण टोकन मिल रहा है। मेरी समझ यह है कि रेलों को केवल एचटीएमएल या जेएस अनुरोधों के लिए प्रामाणिकता टोकन की आवश्यकता होनी चाहिए, और इस प्रकार मुझे इस त्रुटि का सामना नहीं करना चाहिए। एकमात्र समाधान जो मैंने पाया है, वह एपीआई के माध्यम से किसी भी कार्रवाई के लिए protect_from_forgery को अक्षम कर रहा है, लेकिन यह स्पष्ट कारणों से आदर्श नहीं है। विचार?रेल - अमान्य प्रमाणीकरण टोकन जेएसएन/एक्सएमएल अनुरोधों के लिए

def create 
    respond_to do |format| 
     format.html 
     format.json{ 
      render :json => Object.create(:user => @current_user, :foo => params[:foo], :bar => params[:bar]) 
     } 
     format.xml{ 
      render :xml => Object.create(:user => @current_user, :foo => params[:foo], :bar => params[:bar]) 
     } 
    end 
end 

और यह है कि क्या मैं लॉग में मिलता है जब भी मैं कार्रवाई के लिए एक अनुरोध भेज देता है:

Processing FooController#create to json (for 127.0.0.1 at 2009-08-07 11:52:33) [POST] 
Parameters: {"foo"=>"1", "api_key"=>"44a895ca30e95a3206f961fcd56011d364dff78e", "bar"=>"202"} 

ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken): 
    thin (1.2.2) lib/thin/connection.rb:76:in `pre_process' 
    thin (1.2.2) lib/thin/connection.rb:74:in `catch' 
    thin (1.2.2) lib/thin/connection.rb:74:in `pre_process' 
    thin (1.2.2) lib/thin/connection.rb:57:in `process' 
    thin (1.2.2) lib/thin/connection.rb:42:in `receive_data' 
    eventmachine (0.12.8) lib/eventmachine.rb:242:in `run_machine' 
    eventmachine (0.12.8) lib/eventmachine.rb:242:in `run' 
    thin (1.2.2) lib/thin/backends/base.rb:57:in `start' 
    thin (1.2.2) lib/thin/server.rb:156:in `start' 
    thin (1.2.2) lib/thin/controllers/controller.rb:80:in `start' 
    thin (1.2.2) lib/thin/runner.rb:174:in `send' 
    thin (1.2.2) lib/thin/runner.rb:174:in `run_command' 
    thin (1.2.2) lib/thin/runner.rb:140:in `run!' 
    thin (1.2.2) bin/thin:6 
    /opt/local/bin/thin:19:in `load' 
    /opt/local/bin/thin:19 

उत्तर

12

मैं एक ऐसी ही स्थिति थी और समस्या यह है कि मैं सही सामग्री के माध्यम से नहीं भेज रहा था टाइप हेडर - मैं text/json का अनुरोध कर रहा था और मुझे application/json का अनुरोध करना चाहिए था।

मैं curl इस्तेमाल किया अपने आवेदन (को आवश्यकतानुसार बदलें) का परीक्षण करने के बाद:

curl -H "Content-Type: application/json" -d '{"person": {"last_name": "Lambie","first_name": "Matthew"}}' -X POST http://localhost:3000/people.json -i 

या आप एक स्थानीय फाइल करने के लिए JSON बचाने के लिए और curl इस तरह कॉल कर सकते हैं:

curl -H "Content-Type: application/json" -v -d @person.json -X POST http://localhost:3000/people.json -i 

जब मैंने कंटेंट टाइप हेडर को दाएं application/json में बदल दिया है, मेरी सभी परेशानी दूर हो गईं और मुझे अब जाली सुरक्षा को अक्षम करने की आवश्यकता नहीं है।

+0

यह वास्तव में वेब अनुप्रयोगों के लिए हालांकि काम नहीं करता। ब्राउज़र कर्ल नहीं चला सकते हैं। = ( – NullVoxPopuli

+3

बिंदु यह था कि मैंने इस मुद्दे को कर्ल से डीबग किया और पाया कि सही सामग्री-प्रकार शीर्षलेख भेजना महत्वपूर्ण था। – mlambie

19

protect_from_forgery सक्षम के साथ, रेल को किसी गैर-जीईटी अनुरोधों के लिए प्रामाणिकता टोकन की आवश्यकता होती है। रेल स्वचालित रूप से फॉर्म हेल्पर्स या AJAX हेल्पर्स के साथ बनाए गए लिंक के साथ बनाए गए फॉर्मों में प्रामाणिकता टोकन शामिल करेंगे - इसलिए सामान्य मामलों में, आपको इसके बारे में सोचना नहीं होगा।

यदि आप अंतर्निहित रेल फॉर्म या AJAX हेल्पर्स (शायद आप अनजान जेएस कर रहे हैं या जेएस एमवीसी फ्रेमवर्क का उपयोग कर रहे हैं) का उपयोग नहीं कर रहे हैं, तो आपको क्लाइंट साइड पर खुद को टोकन सेट करना होगा और भेजना होगा POST अनुरोध सबमिट करते समय यह आपके डेटा के साथ। आप अपने लेआउट के <head> में इस तरह की एक पंक्ति डाल चाहते हैं:

$.post(url, { 
    id: theId, 
    authenticity_token: window._token 
}); 
+1

ऑप्टिमेट को इस उत्तर को स्वीकार करना चाहिए। वैसे, यदि आप '$ .ajax' का उपयोग करते हैं तो आपको इस तरह के डेटा फ़ील्ड में प्रामाणिकता टोकन डालें: '$ .ajax ({data: {authenticity_token: window._token}})' –

2

अप करने के लिए जोड़ा जा रहा है:

<%= javascript_tag "window._token = '#{form_authenticity_token}'" %> 

फिर अपने AJAX समारोह अपने अन्य डेटा (jQuery के साथ उदाहरण) के साथ टोकन पोस्ट होगा andymism का जवाब आप इस का उपयोग कर सकते हर पोस्ट अनुरोध में टोकन के डिफ़ॉल्ट शामिल किए जाने के लागू करने के लिए:

$(document).ajaxSend(function(event, request, settings) { 
    if (settings.type == 'POST' || settings.type == 'post') { 
     settings.data = (settings.data ? settings.data + "&" : "") 
      + "authenticity_token=" + encodeURIComponent(window._token); 
    } 
}); 
+1

api_key का बिंदु auth_token – NullVoxPopuli

4

एक और तरीका में skip_before_filter का उपयोग कर verify_authenticity_token से बचने के लिए है अपने रेल ऐप:

skip_before_action :verify_authenticity_token, only: [:action1, :action2] 

यह अपनी नौकरी करने के लिए कर्ल देगा।

2

फर्नांडो के जवाब देने के लिए जोड़ने के लिए, अपने नियंत्रक दोनों json और html करने के लिए, आप उपयोग कर सकते हैं प्रतिक्रिया करता है, तो:

 skip_before_filter :verify_authenticity_token, if: :json_request? 
+1

होने से बचने के लिए है क्या यह सुरक्षा जोखिम नहीं है? –

10

यह @user1756254's answer रूप में ही है, लेकिन रेल 5 में आप थोड़ा अधिक विभिन्न सिंटैक्स का उपयोग करने की आवश्यकता है :

protect_from_forgery unless: -> { request.format.json? } 

स्रोत: http://api.rubyonrails.org/v5.0/classes/ActionController/RequestForgeryProtection.html

+3

क्या यह सुरक्षा जोखिम नहीं है? –

+1

@WylliamJudd नहीं, केवल जेएसओएन के लिए इसे अक्षम करने से सुरक्षा जोखिम उत्पन्न नहीं होता है क्योंकि फर्जी सुरक्षा लक्ष्य अन्य साइटों से सबमिट किए गए HTML फॉर्मों की रक्षा करना है – edwardmp

+2

जब आधिकारिक दस्तावेज कहता है: _'if आप इमारत कर रहे हैं एक एपीआई आपको एप्लिकेशन कंट्रोलर में जाली सुरक्षा पद्धति को बदलना चाहिए (डिफ़ॉल्ट रूप से: अपवाद) '_, तो यह पर्याप्त सुरक्षित है –

संबंधित मुद्दे