विकल्प प्रीफ़्लाइट अनुरोध को कैसे छोड़ें?


93

मैंने एक PhoneGap ऐप विकसित किया था जिसे अब एक मोबाइल वेबसाइट में बदला जा रहा है। एक छोटी सी गड़बड़ के अलावा सब कुछ सुचारू रूप से काम करता है। मैं POST अनुरोध के माध्यम से एक निश्चित तृतीय पक्ष API का उपयोग करता हूं, जो ऐप में ठीक काम करता है, लेकिन मोबाइल वेबसाइट संस्करण में विफल रहता है।

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

यह वह कोड है जिसके बारे में मैं बात कर रहा हूं:

        var request = {
                language: 'fr',
                barcodes: [
                    {
                        barcode: 'somebarcode',
                        description: 'Description goes here'
                    }
                ]
            };
        }
        var config = {
            headers: { 
                'Cache-Control': 'no-cache',
                'Content-Type': 'application/json'
            }
        };
        $http.post('http://somedomain.be/trackinginfo', request, config).success(function(data, status) {
            callback(undefined, data);
        }).error(function(data, status) {
            var err = new Error('Error message');
            err.status = status;
            callback(err);
        });

मैं ब्राउज़र (या AngularJS) को उस विकल्प को भेजने से कैसे रोक सकता हूं और वास्तविक POST अनुरोध को छोड़ सकता हूं? मैं AngularJS 1.2.0 का उपयोग कर रहा हूं।

अग्रिम में धन्यवाद।

जवाबों:


100

आपके सामग्री-प्रकार के द्वारा प्रीफ़्लाइट को ट्रिगर किया जा रहा है application/json। इसे रोकने का सबसे सरल तरीका है text/plainकि आपके मामले में सामग्री-प्रकार सेट किया जाए । application/x-www-form-urlencodedऔर multipart/form-dataसामग्री-प्रकार भी स्वीकार्य हैं, लेकिन आप निश्चित रूप से जरूरत के उचित रूप से आपके अनुरोध पेलोड फ़ॉर्मेट करने के लिए होगा।

यदि आप इस परिवर्तन को करने के बाद भी प्रीफ़्लाइट देख रहे हैं, तो हो सकता है कि कोणीय अनुरोध के साथ-साथ एक्स-हेडर भी जोड़ रहा हो।

या आपके पास हेडर हो सकता है (प्राधिकरण, कैश-कंट्रोल ...) जो इसे ट्रिगर करेगा, देखें:


9
यह सही उत्तर है - आपके सामग्री-प्रकार और कैश-नियंत्रण शीर्षलेख पूर्व-अनुरोध अनुरोध को ट्रिगर कर रहे हैं। एक सामग्री-प्रकार के पाठ के साथ एक सादा / सादा और कुछ अन्य गैर-पूर्व-अनुरोधित अनुरोध को ट्रिगर करने के एकमात्र तरीके हैं। देखें: developer.mozilla.org/en-US/docs/HTTP/…
जेफ हबर्ड

आह हाँ, कैश-कंट्रोल के बारे में भूल गया।
रे निकोलस

17
एक कस्टम हेडर भी प्रीफ़्लाइट को ट्रिगर करेगा।
सेबास्टियन डेप्रेज़

2
विकल्प परीक्षण को रोकने के लिए सामग्री प्रकार को बदलना उत्तर नहीं है। सामग्री प्रकार की परवाह किए बिना सामग्री प्रकार से मेल खाना चाहिए
ekerner

यदि यह ब्राउज़र फेंक रहा है, और बैकएंड में, Http विधि विकल्प अवरुद्ध है, तो क्या इसका कोई प्रभाव होगा जैसे ब्राउज़र POST / PUT के लिए संगत API को कॉल नहीं कर रहा है क्योंकि विकल्प विफल हो गया है?
पी सतीश पात्रो

16

जैसा कि रे ने कहा था, आप सामग्री-हेडर को संशोधित करके इसे रोक सकते हैं जैसे -

 $http.defaults.headers.post["Content-Type"] = "text/plain";

उदाहरण के लिए -

angular.module('myApp').factory('User', ['$resource','$http',
    function($resource,$http){
        $http.defaults.headers.post["Content-Type"] = "text/plain";
        return $resource(API_ENGINE_URL+'user/:userId', {}, {
            query: {method:'GET', params:{userId:'users'}, isArray:true},
            getLoggedIn:{method:'GET'}
        });
    }]);

या सीधे कॉल पर -

var req = {
 method: 'POST',
 url: 'http://example.com',
 headers: {
   'Content-Type': 'text/plain'
 },
 data: { test: 'test' }
}

$http(req).then(function(){...}, function(){...});

यह पूर्व-उड़ान विकल्प अनुरोध नहीं भेजेगा।

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


1
मुझे इसे कैसे करना चाहिए $http?
सीखे हुए

धन्यवाद, यह वही है जो मैं कर रहा था। केवल परिवर्तन विधि GETऔर एक अतिरिक्त शीर्ष लेख हैं Authorization। लेकिन फिर भी प्रीफ़लाइट भेज रहा है।
सीखे

1
क्या आप यहां अपना अनुरोध चिपका सकते हैं? कर्ल के रूप में या कुछ और? हो सकता है कि प्राधिकरण हेडर के कारण, इसे हटाने का प्रयास करें और फिर प्रयास करें। यदि आप कस्टम हेडर भेज रहे हैं तो कोणीय पूर्व-उड़ान अनुरोध भेजेगा।
vivex

pastebin.com/vRDeFiH2 पहला $ http का अनुरोध है और दूसरा एक वैध अनुरोध है जिसे डाकिया :) द्वारा निर्मित किया गया है
Learnercys

2

जब कुछ प्रकार के क्रॉस-डोमेन AJAX अनुरोधों का प्रदर्शन करते हैं, तो कॉर्स का समर्थन करने वाले आधुनिक ब्राउज़र यह निर्धारित करने के लिए एक अतिरिक्त "प्रीफ़लाइट" अनुरोध सम्मिलित करेंगे कि क्या उन्हें कार्रवाई करने की अनुमति है या नहीं। उदाहरण क्वेरी से:

$http.get( ‘https://example.com/api/v1/users/’ +userId,
  {params:{
           apiKey:’34d1e55e4b02e56a67b0b66’
          }
  } 
);

इस खंड के परिणामस्वरूप हम देख सकते हैं कि पता दो अनुरोधों (विकल्प और GET) को भेजा गया था। सर्वर की प्रतिक्रिया में हेडर शामिल हैं जो क्वेरी GET की अनुमति की पुष्टि करता है। यदि आपके सर्वर को ठीक से विकल्प अनुरोध संसाधित करने के लिए कॉन्फ़िगर नहीं किया गया है, तो क्लाइंट अनुरोध विफल हो जाएंगे। उदाहरण के लिए:

Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: accept, origin, x-requested-with, content-type
Access-Control-Allow-Methods: DELETE
Access-Control-Allow-Methods: OPTIONS
Access-Control-Allow-Methods: PUT
Access-Control-Allow-Methods: GET
Access-Control-Allow-Methods: POST
Access-Control-Allow-Orgin: *
Access-Control-Max-Age: 172800
Allow: PUT
Allow: OPTIONS
Allow: POST
Allow: DELETE
Allow: GET

2

मुझे लगता है कि सबसे अच्छा तरीका यह जांचना है कि क्या अनुरोध "विकल्प" प्रकार का है जो मध्य वेयर से 200 वापस आता है। इसने मेरे लिए काम किया।

express.use('*',(req,res,next) =>{
      if (req.method == "OPTIONS") {
        res.status(200);
        res.send();
      }else{
        next();
      }
    });

यह काम करता है, लेकिन OWASP में यह विकल्प उजागर नहीं करने की सिफारिश की गई है। आप इसे बैकएंड / होस्टेड सर्विस (नगनेक्स, अपाचे) आदि में ब्लॉक करें
पी सतीश पात्रो

0

Preflight ब्राउज़र द्वारा कार्यान्वित एक वेब सुरक्षा सुविधा है। Chrome के लिए आप --disable-web-security फ़्लैग को जोड़कर सभी वेब सुरक्षा को अक्षम कर सकते हैं।

उदाहरण के लिए: "C: \ Program Files \ Google \ Chrome \ Application \ chrome.exe" --disable-web-security -user-data-dir = "C: \ newChromeSettingsWithoutSecurity"। आप पहले क्रोम का एक नया शॉर्टकट बना सकते हैं, इसके गुणों पर जा सकते हैं और ऊपर के रूप में लक्ष्य को बदल सकते हैं। यह मदद करनी चाहिए!


आप वास्तव में ओपी से यह उम्मीद नहीं कर सकते हैं कि वह अपने ग्राहकों को बताए कि ब्राउज़र सुरक्षा को बंद करने के लिए केवल एक सुविधा को सक्षम करें, सही ?!
svarog

@ svarog यह ज्यादातर देव उद्देश्यों के लिए है, ज्यादातर उत्पादन सर्वर पर आप इस मुद्दे का सामना नहीं करेंगे।
अरिजीत पात्रा

यदि यह ब्राउज़र फेंक रहा है, और बैकएंड में, Http विधि विकल्प अवरुद्ध है, तो क्या इसका कोई प्रभाव होगा जैसे ब्राउज़र POST / PUT के लिए संगत API को कॉल नहीं कर रहा है क्योंकि विकल्प विफल हो गया है?
पी सतीश पात्रो

-2

अपरिभाषित करने के लिए सामग्री-प्रकार की स्थापना करना जावास्क्रिप्ट को हेडर डेटा को पास करना होगा जैसा कि यह है, और डिफ़ॉल्ट कोणीय $ httpProvider हेडर कॉन्फ़िगरेशन लिखना। कोणीय $ http प्रलेखन

$http({url:url,method:"POST", headers:{'Content-Type':undefined}).then(success,failure);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.