2015-02-18 7 views
17

मुझे रिकॉर्ड (या बनाने) को अपडेट करने का प्रयास करते समय एक अमान्य सीएसआरएफ टोकन त्रुटि प्राप्त हो रही है। मैं Elixir v1.0.3, Erlang/OTP 17 [erts-6.3], और फीनिक्स v0.8.0 का उपयोग कर रहा हूं (मुझे लगता है, मुझे यकीन नहीं है कि फीनिक्स के संस्करण को कैसे जांचें)। मैं ज्यादातर फीनिक्स गाइड और एलिक्सीर डोस जॉब्ससाइट उदाहरण संसाधनों के बाद एक वेब ऐप बना रहा हूं। हालांकि, जब मैं एक HTML फॉर्म से जानकारी पोस्ट करने का प्रयास करता हूं, तो मुझे अमान्य सीएसआरएफ टोकन त्रुटि मिलती है। त्रुटि में दी गई सलाह के बाद, मैंने 'x-csrf-token' जोड़ा: कार्रवाई के लिए csrf_token।फीनिक्स - अमान्य सीएसआरएफ (क्रॉस साइट फोर्जरी प्रोटेक्शन) टोकन त्रुटि

edit.html.eex:

<h2>Edit Directory</h2> 
<form class="form-horizontal" action="<%= directory_path @conn, :update, @directory.id, 'x-csrf-token': @csrf_token %>" method="post"> 
    <div class="form-group"> 
    <label for="directory" class="col-sm-2 control-label">Directory</label> 
    <div class="col-sm-10"> 
     <input type="hidden" name="_method" value="PATCH"> 
     <input type="text" class="form-control" value="<%= @directory.directory %>" name="directory" placeholder="Directory" required="required"> 
    </div> 
    </div> 
... 

लेकिन मैं निम्न त्रुटि प्राप्त: जहां तक ​​मेरा बता सकते हैं (अमृत, फीनिक्स, और HTML के लिए नया किया जा रहा है)

[error] #PID<0.579.0> running Ainur.Endpoint terminated 
Server: localhost:4000 (http) 
Request: POST /config/directories/2?x-csrf-token= 
** (exit) an exception was raised: 
    ** (Plug.CSRFProtection.InvalidCSRFTokenError) Invalid CSRF (Cross Site Forgery Protection) token. Make sure that all your non-HEAD and non-GET requests include the csrf_token as part of form params or as a value in your request's headers with the key 'x-csrf-token' 
     (plug) lib/plug/csrf_protection.ex:54: Plug.CSRFProtection.call/2 
     (ainur) web/router.ex:4: Ainur.Router.browser/2 
     (ainur) lib/phoenix/router.ex:2: Ainur.Router.call/2 
     (plug) lib/plug/debugger.ex:104: Plug.Debugger.wrap/3 
     (phoenix) lib/phoenix/endpoint/error_handler.ex:43: Phoenix.Endpoint.ErrorHandler.wrap/3 
     (ainur) lib/ainur/endpoint.ex:1: Ainur.Endpoint.phoenix_endpoint_pipeline/2 
     (plug) lib/plug/debugger.ex:104: Plug.Debugger.wrap/3 
     (phoenix) lib/phoenix/endpoint/error_handler.ex:43: Phoenix.Endpoint.ErrorHandler.wrap/3 

, " कार्रवाई "अनिवार्य रूप से एक पथ है और इसमें जो भी पैरामीटर हैं, वे एप्लिकेशन पर वापस आ जाएंगे। और, वास्तव में, मुझे लगता है कि x-csrf-token = "" राउटर को वापस भेज दिया गया है, इसलिए @csrf_token सही नहीं होना चाहिए। मुझे यकीन नहीं है कि csrf_token कहां से आता है, इसलिए मुझे नहीं पता कि इसका संदर्भ कैसे दिया जाए (या शायद मैं इसे पूरी तरह से गलत कर रहा हूं)।

किसी भी विचार की सराहना की जाएगी।

उत्तर

3

संस्करण स्थापित देखने के लिए,

cat ./deps/phoenix/mix.exs | grep version 

कौन आपको पता चलता है जो फोनिक्स आप deps निर्देशिका में है चलाते हैं।

इसके अलावा, यदि आप फीनिक्स 0.9.0 में अपग्रेड करते हैं, तो चीजें बदल गई हैं (प्लग.CSRFProtection के अपडेट के कारण), सीएसआरएफ सत्रों के बजाय कुकीज़ का उपयोग करके अलग-अलग काम करता है।

से Phoenix changelog for v0.9.0 (2015-02-12)

[Plug] Plug.CSRFProtection now uses a cookie instead of session and expects a "_csrf_token" parameter instead of "csrf_token"

टोकन का मूल्य तक पहुंचने के लिए, कुकी, जो सर्वर साइड पर की तरह

Map.get(@conn.req_cookies, "_csrf_token") 
अपने कोड के लिए

तो लग रहा है से अगर हड़पने,

कुछ ऐसा दिखाई देगा
<h2>Edit Directory</h2> 
<form class="form-horizontal" action="<%= directory_path @conn, :update, @directory.id, 'x-csrf-token': Map.get(@conn.req_cookies, "_csrf_token") %>" method="post"> 
    <div class="form-group"> 
    <label for="directory" class="col-sm-2 control-label">Directory</label> 
    <div class="col-sm-10"> 
     <input type="hidden" name="_method" value="PATCH"> 
     <input type="text" class="form-control" value="<%= @directory.directory %>" name="directory" placeholder="Directory" required="required"> 
    </div> 
    </div> 

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

$.cookie("_csrf_token") 
चलाकर अपने ब्राउज़र में मूल्य को देखने के लिए सक्षम होना चाहिए

कौन सा ऊपर, अंतरिक्ष, फोनिक्स में यूआरएल होने के इनकोडिंग किया गया, जिसमें तरह

"K9UDa23e1sacdadfmvu zzOD9VBHTSr1c/lcvWY=" 

नोट कुछ वापस कर सकती है +, जो अभी भी सीएसआरएफ विफल होने का कारण बन रहा था। अब जब कि प्लग, या बस कुछ में एक बग से संभाला जा रहा है, मैं, यकीन नहीं है तो अब मैं बस CSRF टोकन के उपयोग के साथ स्पष्ट रूप से

$.cookie("_csrf_token").replace(/\s/g, '+'); 

+ निपटने के लिए कर रहा हूँ, अब हम सिर्फ जोड़ने की जरूरत आपके अनुरोध हेडर पर x-csrf-token (thank you ilake)। कोड को AJAX कॉल कार्य के साथ काम करने के लिए यहां दिया गया है (यूआरएल और डेटा भरें और तदनुसार प्रतिक्रिया दें)।

$.ajax({ 
    url: 'YOUR URL HERE', 
    type: 'POST', 
    beforeSend: function(xhr) { 
    xhr.setRequestHeader('x-csrf-token', $.cookie("_csrf_token").replace(/\s/g, '+')) 
    }, 
    data: 'someData=' + someData, 
    success: function(response) { 
    $('#someDiv').html(response); 
    } 
}); 

ध्यान दें कि आप के रूप में अच्छी पैरामीटर के रूप में _csrf_token वापस भेज सकता है, लेकिन मैं इसके बाद के संस्करण पसंद करते हैं और यह मेरे लिए क्लीनर लगता है।

अंतिम नोट, मेरे पास jquery कुकी के लिए एक लिंक पोस्ट करने के लिए पर्याप्त प्रतिष्ठा अंक नहीं थे, लेकिन यह Google के लिए आसान होना चाहिए।

+0

विस्तृत प्रतिक्रिया के लिए धन्यवाद। यह पता चला है कि मैं फीनिक्स 0.8.0 चला रहा हूं, इसलिए नीचे दिया गया कोड काम करता है, लेकिन जब आप 0.9.0 में अपग्रेड करते हैं तो आपने मुझे एक बड़ा सिरदर्द बचा लिया है! –

+0

धन्यवाद फिर से @ a4word, मैंने फीनिक्स 0.9.0 में अपग्रेड किया और कुकी से टोकन प्राप्त करने के लिए टेम्पलेट को बदल दिया। हालांकि, आश्चर्यजनक रूप से पर्याप्त, ऐसा लगता है, लेकिन मुझे अभी भी एक अवैध सीएसआरएफ (क्रॉस साइट फोर्जरी प्रोटेक्शन) टोकन त्रुटि मिल रही है। टोकन 'ne0GATpoc/EW6jbIbC7tmfkAWl4qb1opTPWmmfYFTRY =' (कोई रिक्त स्थान नहीं है) और टेम्पलेट एक यूआरएल 'POST/config/निर्देशिका/9 बनाता है? X-csrf-token = ne0GATpoc% 2FEW6jbIbC7tmfkAWl4qb1opTPWmmfYFTRY% 3 डी' मुझे नहीं पता कि प्लग.CSRFProtection क्यों नहीं करता है पसंद है। क्या आप जानते हैं या मुझे एक और सवाल खोलना चाहिए? –

+0

मैंने टेम्पलेट में टोकन का नाम बदल दिया: 'x-csrf-token ": Map.get (@ conn.req_cookies," _csrf_token ")' to: '' _csrf_token ': Map.get (@ conn.req_cookies , "_csrf_token") 'और अब यह काम करता है। –

1

मुझे http://phoenix.thefirehoseproject.com पर उत्तर मिला। आप CSRF टोकन प्राप्त करने के समारोह बनाना चाहिए:

वेब/view.ex

def csrf_token(conn) do 
    Plug.Conn.get_session(conn, :csrf_token) 
end 

फिर टेम्पलेट में इसे पुनः प्राप्त:

वेब/टेम्पलेट/directory/edit.html.eex

<form class="form-horizontal" action="<%= directory_path @conn, :update, @directory.id %>" method="post"> 
    <input type="hidden" name="csrf_token" value="<%= csrf_token(@conn) %>"> 

और यही वह है!

19

फीनिक्स के संस्करण 0.13 पर आप

<input type="hidden" name="_csrf_token" value="<%= get_csrf_token() %>"> 

इस समारोह की एक आयात वहाँ फ़ाइल web/web.ex पर क्योंकि कर सकते हैं।

+0

धन्यवाद! मैं बस 0.13 के उन्नयन की प्रक्रिया में था। –

+0

धन्यवाद - v0.12 -> 0.13 से उत्पन्न वेब/web.ex में यह एकमात्र परिवर्तन है – Jay

6

v0.10.0 के बाद से एक और समाधान उपलब्ध है, तो आप फीनिक्स को आपके लिए सीएसआरएफ इनपुट इंजेक्ट करने दे सकते हैं।

Example from upgrade guide:

<%= form_tag("/hello", method: :post) %> 
... your form stuff. input with csrf value is created for you. 
</form> 

कि उत्पादन प्रपत्र टैग और _csrf_token एक सहित कुछ इनपुट टैग,। परिणाम कुछ इस तरह दिखेगा:

<form accept-charset="UTF-8" action="/hello" method="post"> 
    <input name="_csrf_token" value="[automatically-inserted token]" type="hidden"> 
    <input name="_utf8" value="✓" type="hidden"> 
</form> 

form_tag docs: "। 'पोस्ट के अनुरोध के लिए, प्रपत्र टैग नाम _csrf_token साथ एक इनपुट टैग स्वतः शामिल हो जाएगी"

0

मेरे मामले में यह समस्या plug :scrub_params समस्या उत्पन्न कर रही थी। लाइन पर टिप्पणी करने के बाद, यह काम किया। लेकिन इसे ठीक करने के लिए सुनिश्चित करने की आवश्यकता है क्योंकि ऐप scrub_params के बिना असुरक्षित होगा।

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