2017-03-14 17 views
6

मैं एक रेल 5 एपीआई एप्लिकेशन (ApplicationController < ActionController::API) है। इस एपीआई के एक एंडपॉइंट के लिए एक साधारण जीयूआई फॉर्म जोड़ने की जरूरत आई है।रेल 5 एपीआई protect_from_forgery

शुरू में मैं ActionView::Template::Error undefined method protect_against_forgery? हो रही थी जब मैं प्रपत्र प्रस्तुत करना करने की कोशिश की। मैंने उस एंडपॉइंट पर include ActionController::RequestForgeryProtection और protect_from_forgery with:exception जोड़ा। जिसने उम्मीद के अनुसार उस मुद्दे को हल किया।

हालांकि, जब मैं इस फॉर्म को सबमिट करने का प्रयास करता हूं तो मुझे मिलता है: 422Unprocessable EntityActionController::InvalidAuthenticityToken। मैं <%= csrf_meta_tags %> जोड़ दिया है और पता लगाया कि meta: csrf-param और meta: csrf-token मेरी हेडर में मौजूद हैं, और कहा कि authenticity_token मेरी रूप में मौजूद है। (टोकन के लिए खुद को एक दूसरे से अलग कर रहे हैं।)

मैं कोशिश की है, protect_from_forgery prepend: true, with:exception, कोई प्रभाव नहीं। मैं टिप्पणी करके इस समस्या को "ठीक" कर सकता हूं: protect_from_forgery with:exception। लेकिन मेरी समझ यह है कि यह मेरे रूप में सीएसआरएफ सुरक्षा बंद कर रहा है। (मैं CSRF संरक्षण चाहते हैं।)

मैं क्या याद आ रही है?

अद्यतन:

यह स्पष्ट, इस एप्लिकेशन के 99% एक शुद्ध JSON RESTful API है बनाने की कोशिश करने के लिए। इस ऐप में एक HTML व्यू और फॉर्म जोड़ने की आवश्यकता आई है। तो एक नियंत्रक के लिए मैं पूर्ण सीएसआरएफ सुरक्षा सक्षम करना चाहता हूं। शेष ऐप को सीएसआरएफ की आवश्यकता नहीं है और अपरिवर्तित रह सकता है।

अद्यतन 2:

मैं सिर्फ एक और पारंपरिक रेल 5 एप्लिकेशन मैंने लिखा से इस एप्लिकेशन के HTML प्रपत्र और हैडर के पेज स्रोत की तुलना में। हैडर में authenticity_token और रूप में authenticity_tokenही हैं। एपीआई ऐप में मुझे समस्या है, वे अलग हैं। शायद यह कुछ है?

अद्यतन 3:

ठीक है, मैं बेमेल नहीं है मुद्दा है। हालांकि, काम करने वाले और गैर-काम करने वाले ऐप्स के बीच और तुलना में मैंने देखा कि नेटवर्क> कुकीज में कुछ भी नहीं है। मैं काम करने वाले ऐप की कुकीज़ में _my_app-session जैसी चीजों का एक गुच्छा देखता हूं।

उत्तर

11

यहाँ मुद्दा था है: रेल 5, जब एपीआई मोड में, तार्किक रूप से कुकी मिडलवेयर शामिल नहीं है। इसके बिना, मेरे फॉर्म के साथ पारित टोकन को सत्यापित करते समय उपयोग किए जाने वाले कुकी में संग्रहीत कोई सत्र key कोई सत्र नहीं है।

कुछ हद तक भ्रमित, config/initializers/session_store.rb में चीजों को बदलने से कोई प्रभाव नहीं पड़ा।

मैं अंत में यहाँ है कि समस्या का जवाब मिला: Adding cookie session store back to Rails API app है, जो मुझे यहाँ का नेतृत्व किया: https://github.com/rails/rails/pull/28009/files जो वास्तव में लाइनों मैं वापस काम कर कुकीज़ पाने के लिए application.rb में जोड़ने के लिए की जरूरत का उल्लेख किया:

config.session_store :cookie_store, key: "_YOUR_APP_session_#{Rails.env}" 
config.middleware.use ActionDispatch::Cookies # Required for all session management 
config.middleware.use ActionDispatch::Session::CookieStore, config.session_options 

उन तीन लाइनों के साथ मिलकर:

class FooController < ApplicationController 
    include ActionController::RequestForgeryProtection 
    protect_from_forgery with: :exception, unless: -> { request.format.json? } 
    ... 

और निश्चित रूप से एक फार्म उचित सहायकों के माध्यम से उत्पन्न:

form_tag(FOO_CREATE_path, method: :post) 
    ... 

मुझे मेरे रेल एपीआई ऐप के बीच में एक सीएसआरएफ संरक्षित फॉर्म मिला।

+1

यह अप्रत्याशित रूप से स्पष्ट नहीं है कि आपको एपीआई मोड में form_tag का उपयोग पहली जगह क्यों करना होगा। एपीआई मोड का विचार आपके बैकएंड को शुद्ध डेटा एंडपॉइंट के रूप में किसी भी UI प्रतिनिधित्व उत्पन्न करने के लिए ज़िम्मेदार नहीं है। –

+0

@ फ़ैब्रिज़ियोबर्टोग्लियो नहीं, न तो मैंने जो कहा है, न ही आपका कथन सत्य है। यह संभव है कि आपको एपीआई ऐप्स में सीएसआरएफ हमलों के बारे में चिंता करने की ज़रूरत है। एक उदाहरण है कि आपको सीएसआरएफ के बारे में चिंता करने की ज़रूरत है कि जब आपकी एपीआई सेवा कुकीज़ का उपयोग करती है। –

1

यदि आप रेल 5 एपीआई मोड का उपयोग कर रहे हैं, तो आप protect_from_forgery का उपयोग नहीं करते हैं या किसी भी दृश्य में <%= csrf_meta_tags %> शामिल नहीं करते हैं क्योंकि आपका एपीआई 'स्टेटलेस' है।

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

ताकि protect_from_forgery कहा जा सकता है जब उचित हो: यदि आप करते हुए भी अन्य एप्लिकेशन/ग्राहकों के लिए एक REST API के रूप में उपयोग पूर्ण रेल (नहीं एपीआई मोड) का उपयोग करने के लिए जा रहे थे, तो आप कुछ इस तरह कर सकता है । लेकिन मुझे आपके कोड में ActionController::API दिखाई देता है, ऐसा लगता है कि आप एपीआई मोड का उपयोग कर रहे हैं, इस मामले में आप अपने एप्लिकेशन कंट्रोलर से विधि को हटा देंगे

+0

ऐप _was_ एक शुद्ध रीस्टफुल एपीआई, सभी जेसन। अब इस ऐप में एक HTML व्यू और फॉर्म जोड़ने की ज़रूरत है। तो, उस नियंत्रक_ के लिए _just मैं एपीआई मोड से बाहर निकलना चाहता हूं और सीएसआरएफ सुरक्षा सक्षम करना चाहता हूं। – lostphilosopher

+0

मैंने इस समाधान को आजमाया है, लेकिन मुझे अभी भी 'सीएसआरएफ टोकन प्रामाणिकता सत्यापित नहीं कर सकता है।' जब मैं फॉर्म पोस्ट करने का प्रयास करता हूं ... – lostphilosopher

+0

आपके विचार के लिए, क्या आप 'erb' का उपयोग कर रहे हैं और' % = form_tag%> '? –

2

AJAX कॉल और एपीआईएस के लिए protect_from_forgery की कोई आवश्यकता नहीं है।

आप कुछ कार्रवाई के लिए उसे निष्क्रिय करना चाहते हैं तो

protect_from_forgery except: ['action_name'] 
+0

हां, मेरा सवाल यह है कि इसे एक नियंत्रक के _non_-API कॉल के लायक के लिए कैसे सक्रिय किया जाए? मेरे पास _one_ HTML पृष्ठ और फ़ॉर्म है जिसे मैं CSRF सुरक्षा चाहता हूं, बाकी ऐप एक विश्वसनीय JSON API है और इसकी आवश्यकता नहीं है। मैं उस नियंत्रक को 'protect_from_forgery' जोड़ने' मान रहा था, जिसमें 'एक्शनकंट्रोलर :: RequestForgeryProtection' शामिल है, यह होगा, लेकिन अब जब मैं उस फॉर्म को सबमिट करने का प्रयास करता हूं तो मुझे' अवैध प्रमाणीकरण टोकन 'मिल रहा है। – lostphilosopher

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