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


91

मैं POST requestअपने स्थानीय देव को इस तरह बनाना चाहता हूं:

  HTTParty.post('http://localhost:3000/fetch_heroku',
                :body => {:type => 'product'},)

हालाँकि, सर्वर कंसोल से यह रिपोर्ट करता है

Started POST "/fetch_heroku" for 127.0.0.1 at 2016-02-03 23:33:39 +0800
  ActiveRecord::SchemaMigration Load (0.0ms)  SELECT "schema_migrations".* FROM "schema_migrations"
Processing by AdminController#fetch_heroku as */*
  Parameters: {"type"=>"product"}
Can't verify CSRF token authenticity
Completed 422 Unprocessable Entity in 1ms

यहाँ मेरा नियंत्रक और मार्ग सेटअप है, यह काफी सरल है।

  def fetch_heroku
    if params[:type] == 'product'
      flash[:alert] = 'Fetch Product From Heroku'
      Heroku.get_product
    end
  end

  post 'fetch_heroku' => 'admin#fetch_heroku'

मुझे यकीन नहीं है कि मुझे क्या करने की आवश्यकता है? CSRF को बंद करने के लिए निश्चित रूप से काम करेगा, लेकिन मुझे लगता है कि इस तरह की एपीआई बनाते समय मेरी गलती होनी चाहिए।

क्या कोई अन्य सेटअप है जो मुझे करने की आवश्यकता है?


5
एपीआई के लिए आम तौर पर सीएसआरएफ टोकन सत्यापन को बंद करने के लिए स्वीकार किया जाता है । मैं उपयोग करता हूं protect_from_forgery with: :null_session
दशहरा

जवाबों:


111

क्रॉस साइट अनुरोध जालसाजी (CSRF / XSRF) तब होता है जब एक दुर्भावनापूर्ण वेब पेज उपयोगकर्ताओं को एक अनुरोध करने के लिए प्रेरित करता है जो कि बुकमार्क, iframes या बस एक पेज बनाकर उदाहरण के लिए अभिप्रेत नहीं है जो उपयोगकर्ताओं को मूर्ख बनाने के लिए नेत्रहीन समान है।

रेल CSRF संरक्षण "शास्त्रीय" वेब ऐप्लिकेशन के लिए किया जाता है - यह केवल आश्वासन के एक डिग्री है कि अनुरोध अपने स्वयं के वेब एप्लिकेशन से उत्पन्न कर देता है। एक CSRF टोकन एक रहस्य की तरह काम करता है जिसे केवल आपका सर्वर जानता है - रेल एक यादृच्छिक टोकन उत्पन्न करता है और इसे सत्र में संग्रहीत करता है। आपके प्रपत्र एक छिपे हुए इनपुट के माध्यम से टोकन भेजते हैं और रेल सत्यापित करता है कि किसी भी गैर GET अनुरोध में एक टोकन शामिल है जो सत्र में संग्रहीत है।

हालाँकि, एक API आमतौर पर डेफिनिशन क्रॉस साइट के द्वारा होता है और इसका उपयोग आपके वेब ऐप से अधिक में किया जाता है, जिसका अर्थ है कि CSRF की पूरी अवधारणा काफी लागू नहीं होती है।

इसके बजाय आपको एपीआई कुंजी के साथ एपीआई अनुरोधों को प्रमाणित करने की एक गुप्त आधारित रणनीति का उपयोग करना चाहिए और जब से आप यह सत्यापित कर रहे हैं कि अनुरोध स्वीकृत एपीआई क्लाइंट से आता है - आपके अपने ऐप से नहीं।

आप CSRF को निष्क्रिय कर सकते हैं जैसा कि @dastyari द्वारा बताया गया है:

class ApiController < ActionController::Base
  protect_from_forgery with: :null_session
end

अपडेट किया गया। रेल 5 में आप केवल --apiविकल्प का उपयोग करके एपीआई उत्पन्न कर सकते हैं :

rails new appname --api

वे CSRF मिडलवेयर और कई अन्य घटकों को शामिल नहीं करते हैं जो सुपरफ्लॉस हैं।


धन्यवाद, मैं CSRF का हिस्सा बंद करने का विकल्प चुनता हूं: stackoverflow.com/questions/5669322/…
cqcn1991

4
इससे पता चलता है कि सभी एपीआई एप्लिकेशन-टू-एप्लिकेशन ट्रैफ़िक की सेवा करते हैं (जिसमें एक एकल साथी को एक अद्वितीय कुंजी और गुप्त जारी किया जाता है)। उस परिदृश्य में, सर्वर से सर्वर संचार की तरह, यह उत्तर उपयुक्त है। फिर भी, अधिकांश वेब ऐप डेवलपर्स के लिए जो भ्रामक है, वह यह है कि जावास्क्रिप्ट क्लाइंट के लिए, आपके द्वारा नियंत्रित और लिखित, आप एक ही कुंजी-रहस्य का उपयोग नहीं करना चाहते हैं (जो सभी ग्राहकों के लिए एक एकल कुंजी-रहस्य उजागर करेगा)। इसके बजाय, रेल का CSRF और कुकी सत्र तंत्र महान कार्य करता है - यहां तक ​​कि जावास्क्रिप्ट एप्लिकेशन के लिए जो आपके एपीआई का उपयोग करते हैं- यदि आप प्रत्येक अनुरोध के साथ CSRF टोकन को रेल में वापस भेजते हैं।
जेसन एफबी

जिस तरह से आप AJAX में इसे करते हैं, वह इस SO पोस्ट stackoverflow.com/questions/7203304/…
जेसन FB

@JasonFB आप सही हैं कि जावास्क्रिप्ट क्लाइंट्स के साथ एक भी रहस्य काम नहीं करता है। हालांकि सत्र और रेल सीएसआरएफ सुरक्षा का उपयोग करना अभी भी समस्याग्रस्त है यदि आप एक एपीआई बनाने का इरादा रखते हैं जिसका उपयोग अन्य प्रकार के गैर-ब्राउज़र क्लाइंट द्वारा भी किया जा सकता है।
अधिकतम

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

79

CSRF को बंद करने का एक और तरीका जो एक अशक्त सत्र को प्रस्तुत नहीं करेगा, वह है:

skip_before_action :verify_authenticity_token

आपके रेल नियंत्रक में। यह सुनिश्चित करेगा कि आपके पास अभी भी सत्र जानकारी तक पहुंच है।

फिर, सुनिश्चित करें कि आप केवल API नियंत्रकों या अन्य स्थानों पर ऐसा करते हैं जहां CSRF सुरक्षा काफी लागू नहीं होती है।


1
यह वही से है protect_from_forgery except: [:my_method_name]?
अर्नोल्ड रोआ

19

Api.rubyonrails.org पर एपीआई नियंत्रकों के संबंध में CSRF के विन्यास पर प्रासंगिक जानकारी है :

यह याद रखना महत्वपूर्ण है कि XML या JSON अनुरोध भी प्रभावित होते हैं और यदि आप एक एपीआई का निर्माण कर रहे हैं, तो आपको जालसाजी संरक्षण विधि को ApplicationController(द्वारा में परिवर्तित करना चाहिए :exception):

class ApplicationController < ActionController::Base
  protect_from_forgery unless: -> { request.format.json? }
end

हम एपीआई के लिए CSRF सुरक्षा को निष्क्रिय करना चाहते हैं क्योंकि वे आमतौर पर राज्य-कम करने के लिए डिज़ाइन किए जाते हैं। यही है, अनुरोध API क्लाइंट रेल के बजाय आपके लिए सत्र को संभाल लेगा।


4
यह कितना भ्रामक है। मैं उन स्रोतों के बीच देख रहा हूँ जो कहते हैं कि protect_from_forgeryअभी भी एपीआई के लिए आवश्यक है, और सूत्रों का कहना है कि ऐसा नहीं है। क्या होगा यदि एपीआई एकल पृष्ठ ऐप के लिए है, जो उपयोगकर्ता प्रमाणीकरण के लिए सत्र कुकी का उपयोग करता है?
व्यालियम जुड

CSRF तंत्र सत्र कुकीज़ का उपयोग करके हमले के वेक्टर से निपटने के लिए रेल्स निर्मित तरीका है। रेल सत्र कुकी के साथ (वास्तव में अंदर) संचालित करते हुए तंत्र आपके नियंत्रकों की सुरक्षा करता है। Protect_from_forgery के बिना, या इसे बंद करने या उस पर एक सेटिंग को सेट करने के बिना, आप CSRF टोकन (जो कि सत्र कुकी से लिया गया है) की जानकारी का उपयोग करके उस कार्रवाई को बचाने के लिए रेल्स नहीं बता रहे हैं।
जेसन एफबी

5
मुझे लगता है कि जो भ्रामक है वह यह है कि रेल प्रलेखन के लिए "एपीआई" का अर्थ है सर्वर-से-सर्वर अनुप्रयोग जो विश्वसनीय, दूरस्थ साझेदारों (आपकी साइट पर आने वाले सभी वेब उपयोगकर्ता नहीं) से एपीआई अनुरोध प्राप्त करेगा। उन पीपीएल के लिए, सुरक्षित गैर-हैक करने योग्य तंत्र के माध्यम से अद्वितीय कुंजी-गुप्त जोड़े दें। आधुनिक वेब एप्लिकेशन के लिए, जहां बहुत से लोग आपके वेब ऐप को वेब क्लाइंट के माध्यम से लोड करेंगे, फिर भी आप प्रत्येक व्यक्ति को आपकी साइट पर आने वाले लोगों की पहचान करने के लिए एक सत्र या टोकन-आधारित तंत्र का उपयोग करते हैं। इसलिए जब तक आप ऐसा करने के लिए कुछ अन्य तंत्र का उपयोग नहीं कर रहे हैं (Json Web tokens, आदि), Rails के अंतर्निहित सामान के साथ रहें।
जेसन एफबी

1
जिस तरह से आप AJAX में इसे करते हैं, वह इस SO पोस्ट stackoverflow.com/questions/7203304/…
जेसन FB

13

5 रेल के बाद से आप :: बेस के बजाय :: एपीआई के साथ एक नया वर्ग भी बना सकते हैं :

class ApiController < ActionController::API
end

3

यदि आप सैंपल कंट्रोलर के सैंपल एक्शन को बाहर करना चाहते हैं

class TestController < ApplicationController
  protect_from_forgery :except => [:sample]

  def sample
     render json: @hogehoge
  end
end

आप बिना किसी समस्या के बाहर से अनुरोधों को संसाधित कर सकते हैं।


0

समस्या का सबसे सरल समाधान आपके नियंत्रक में मानक चीजें हैं या आप इसे सीधे ApplicationController में डाल सकते हैं

class ApplicationController < ActionController::Base protect_from_forgery with: :exception, prepend: true end


0

यदि आप केवल एक या अधिक नियंत्रक क्रियाओं के लिए CSRF सुरक्षा को छोड़ना चाहते हैं (संपूर्ण नियंत्रक के बजाय), तो यह प्रयास करें

skip_before_action :verify_authenticity_token, only [:webhook, :index, :create]

[:webhook, :index, :create]उन 3 कार्यों के लिए चेक को कहां छोड़ेंगे, लेकिन आप जिसे भी छोड़ना चाहते हैं उसे बदल सकते हैं

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