असुरक्षित प्रतिक्रिया या कनेक्शन से इनकार करने के कारण यदि अजाक्स कॉल विफल हो गया है तो निर्धारित करें


115

मैं बहुत शोध कर रहा हूं और इसे संभालने का कोई तरीका नहीं खोज सका। मैं एक jQuery के ajax कॉल करने का प्रयास कर रहा हूं एक https सर्वर से एक लोकास्ट https सर्वर से एक कस्टम स्व हस्ताक्षरित प्रमाण पत्र के साथ जेटी चल रहा है। मेरी समस्या यह है कि मैं यह निर्धारित नहीं कर सकता कि प्रतिक्रिया से इनकार किया गया कनेक्शन है या असुरक्षित प्रतिक्रिया (प्रमाणपत्र स्वीकृति की कमी के कारण)। क्या दोनों परिदृश्यों के बीच अंतर को निर्धारित करने का एक तरीका है? responseText, और statusCodeहमेशा दोनों ही मामलों में एक ही हैं, भले ही क्रोम कंसोल में मैं एक अंतर देख सकते हैं:

net::ERR_INSECURE_RESPONSE
net::ERR_CONNECTION_REFUSED

responseTextहमेशा "" है और statusCodeदोनों मामलों के लिए हमेशा "0" है।

मेरा सवाल है, मैं कैसे निर्धारित कर सकता हूं कि एक jQuery के AJAX कॉल के कारण ERR_INSECURE_RESPONSEया उसके कारण विफल हुआ है ERR_CONNECTION_REFUSED?

एक बार प्रमाणपत्र स्वीकार कर लेने के बाद सबकुछ ठीक हो जाता है, लेकिन मैं जानना चाहता हूं कि क्या लोकलहोस्ट सर्वर बंद है, या फिर वह ऊपर और चल रहा है, लेकिन प्रमाणपत्र अभी तक स्वीकार नहीं किया गया है।

$.ajax({
    type: 'GET',
    url: "https://localhost/custom/server/",
    dataType: "json",
    async: true,
    success: function (response) {
        //do something
    },
    error: function (xhr, textStatus, errorThrown) {
        console.log(xhr, textStatus, errorThrown); //always the same for refused and insecure responses.
    }
});

यहां छवि विवरण दर्ज करें

यहां तक ​​कि मैन्युअल रूप से अनुरोध करने पर भी मुझे वही परिणाम मिलता है:

var request = new XMLHttpRequest();
request.open('GET', "https://localhost/custom/server/", true);
request.onload = function () {
    console.log(request.responseText);
};
request.onerror = function () {
    console.log(request.responseText);
};
request.send();

6
मैं अपना कोड पोस्ट करूंगा, लेकिन यह एक जावास्क्रिप्ट कोड त्रुटि नहीं है। कृपया मेरे सवाल को ध्यान से पढ़ें।
करिकला

1
क्या अन्य दो त्रुटि कॉलबैक तर्क कोई अतिरिक्त जानकारी देते हैं? function (xhr, status, msg) {...मुझे संदेह है कि वे करेंगे, लेकिन कोशिश करने लायक।
केविन बी

2
नंबर एक सर्वर से दूसरे सर्वर पर। जेटी सर्वर (लोकोहास्ट में चल रहा है) ने ठीक से कोर हेडर सेट किया है क्योंकि एक बार जब मैं प्रमाण पत्र स्वीकार करता हूं तो सब कुछ उम्मीद के मुताबिक काम करता है। मैं यह निर्धारित करना चाहता हूं कि क्या प्रमाण पत्र को स्वीकार करना है या जेटी नीचे है।
करिकला

5
यह पूरी तरह से संभव है कि ब्राउज़र से जानकारी की कमी पूरी तरह से जानबूझकर हो। बस एक "त्रुटि" प्रस्तावित हैकर को कुछ मात्रा में जानकारी प्रदान करेगी, जैसे। "इस सिस्टम में पोर्ट आदि पर कुछ सुनना है।"
कटान ३१४

1
यह ऐसा कुछ नहीं है जो मैं चाहता हूं, यह कुछ ऐसा है जिसे मुझे डिजाइन और स्वभाव से चाहिए जो मैं विकसित कर रहा हूं। सर्वर साइड एक विकल्प नहीं है।
करिकला

जवाबों:


67

नवीनतम वेब ब्राउज़र से इसे अलग करने का कोई तरीका नहीं है।

W3C विशिष्टता:

नीचे दिए गए चरणों का वर्णन है कि एक साधारण क्रॉस-ऑरिजिन अनुरोध के लिए उपयोगकर्ता एजेंटों को क्या करना चाहिए :

अनुरोध चरण बनाएं और अनुरोध करते समय नीचे दिए गए अनुरोध नियमों का पालन करें।

यदि मैन्युअल रीडायरेक्ट ध्वज अप्रचलित है और प्रतिक्रिया में 301, 302, 303, 307, या 308 का HTTP स्थिति कोड है, तो रीडायरेक्ट चरणों को लागू करें।

यदि अंतिम उपयोगकर्ता अनुरोध को रद्द कर देता है तो गर्भपात के चरणों को लागू करें।

यदि कोई नेटवर्क त्रुटि है DNS त्रुटियों, TLS बातचीत विफलता या नेटवर्क त्रुटियों के अन्य प्रकार के मामले में, नेटवर्क त्रुटि चरण लागू करें । किसी भी प्रकार के अंतिम उपयोगकर्ता सहभागिता का अनुरोध न करें।

नोट: इसमें HTTP प्रतिक्रियाएँ शामिल नहीं हैं जो कुछ प्रकार की त्रुटि को इंगित करती हैं, जैसे HTTP स्थिति कोड 410।

अन्यथा संसाधन साझाकरण जांच करें। यदि यह विफल रहता है, तो नेटवर्क त्रुटि चरण लागू करें। अन्यथा, यदि यह पास हो जाता है, तो इस एल्गोरिथ्म को समाप्त करें और सफलता के लिए क्रॉस-मूल अनुरोध स्थिति सेट करें। वास्तव में अनुरोध को समाप्त न करें।

जैसा कि आप पढ़ सकते हैं, नेटवर्क त्रुटियों में HTTP प्रतिक्रिया शामिल नहीं है जिसमें त्रुटियां शामिल हैं, यही कारण है कि आपको हमेशा स्थिति कोड के रूप में 0 मिलेगा, और "" त्रुटि है।

स्रोत


नोट : निम्न उदाहरण Google Chrome संस्करण 43.0.2357.130 का उपयोग करके बनाए गए थे और एक वातावरण के खिलाफ जो मैंने ओपी एक का अनुकरण करने के लिए बनाया है। इसे सेट करने के लिए कोड उत्तर के निचले भाग में है।


हालांकि मुझे लगता है कि इस के आसपास काम करने के लिए HTTPS के बजाय HTTP पर एक द्वितीयक अनुरोध किया जाएगा क्योंकि यह उत्तर है लेकिन मुझे याद है कि ब्राउज़रों के नए संस्करण मिश्रित सामग्री को ब्लॉक करने के कारण संभव नहीं है।

इसका मतलब है कि अगर आप HTTPS का उपयोग कर रहे हैं और इसके विपरीत वेब ब्राउज़र HTTP पर अनुरोध नहीं करेगा।

यह कुछ साल पहले से ऐसा है, लेकिन पुराने वेब ब्राउज़र संस्करण जैसे मोज़िला फ़ायरफ़ॉक्स इसके नीचे के संस्करण 23 इसकी अनुमति देते हैं।

इसके बारे में साक्ष्य:

एचटीटीपीएस से HTTP अनुरोध करना वेब ब्रोसर कंसोल को असाइन करता है

var request = new XMLHttpRequest();
request.open('GET', "http://localhost:8001", true);
request.onload = function () {
    console.log(request.responseText);
};
request.onerror = function () {
    console.log(request.responseText);
};
request.send();

निम्नलिखित त्रुटि का परिणाम होगा:

मिश्रित सामग्री: HTTPS पर ' https: // localhost: 8000 / ' पेज लोड किया गया था, लेकिन एक असुरक्षित XMLHttpRequest समापन बिंदु ' http: // localhost: 8001 / ' का अनुरोध किया । इस अनुरोध को अवरुद्ध कर दिया गया है; सामग्री को HTTPS पर परोसा जाना चाहिए।

यदि आप अन्य तरीकों से ऐसा करने का प्रयास करते हैं तो एक समान त्रुटि ब्राउज़र कंसोल में दिखाई देगी।

<iframe src="http://localhost:8001"></iframe>

सॉकेट कनेक्शन का उपयोग करना भी एक उत्तर के रूप में पोस्ट किया गया था, मुझे पूरा यकीन था कि परिणाम समान / समान होगा लेकिन मैंने इसे आज़माया है।

HTTPS से नॉन सिक्योर सॉकेट एंडपॉइंट का उपयोग करके वेब ब्रॉसर से एक सॉकेट कनेक्शन खोलने की कोशिश मिश्रित सामग्री त्रुटियों में समाप्त हो जाएगी।

new WebSocket("ws://localhost:8001", "protocolOne");

1) मिश्रित सामग्री: HTTPS पर ' https: // localhost: 8000 / ' पेज लोड किया गया, लेकिन असुरक्षित WebSocket समापन बिंदु 'ws: // localhost: 8001 /' से कनेक्ट करने का प्रयास किया गया। इस अनुरोध को अवरुद्ध कर दिया गया है; यह समापन बिंदु WSS पर उपलब्ध होना चाहिए।

2) अनकैप्ड DOMException: 'WebSocket' का निर्माण करने में विफल: HTTPS पर लोड किए गए पेज से असुरक्षित WebSocket कनेक्शन शुरू नहीं किया जा सकता है।

फिर मैंने एक wss एंडपॉइंट से कनेक्ट करने की कोशिश की, यह भी देखें कि क्या मैं नेटवर्क कनेक्शन त्रुटियों के बारे में कुछ जानकारी पढ़ सकता हूं:

var exampleSocket = new WebSocket("wss://localhost:8001", "protocolOne");
exampleSocket.onerror = function(e) {
    console.log(e);
}

सर्वर के साथ ऊपर स्निपेट निष्पादित करने के परिणाम सामने आए:

WebSocket कनेक्शन 'wss: // localhost: 8001 /' विफल: कनेक्शन स्थापना में त्रुटि: शुद्ध :: ERR_CONNECTION_REFUSED

सर्वर के साथ ऊपर स्निपेट को निष्पादित करना चालू हो गया

WebSocket कनेक्शन 'wss: // localhost: 8001 /' विफल: WebSocket खोलने के हैंडशेक को रद्द कर दिया गया था

लेकिन फिर से, कंसोल पर "ऑनरोर फ़ंक्शन" आउटपुट में जो त्रुटि है, वह किसी भी अन्य की एक त्रुटि को अलग करने के लिए कोई टिप नहीं है।


इस उत्तर के रूप में एक प्रॉक्सी का उपयोग करना सुझाव काम कर सकता है, लेकिन केवल अगर "लक्ष्य" सर्वर में सार्वजनिक पहुंच है।

यहां ऐसा नहीं था, इसलिए इस परिदृश्य में एक प्रॉक्सी को लागू करने की कोशिश करने से हमें उसी समस्या का सामना करना पड़ेगा।

कोड बनाने के लिए Node.js HTTPS सर्वर :

मैंने दो Nodejs HTTPS सर्वर बनाए हैं, जो स्व हस्ताक्षरित प्रमाणपत्र का उपयोग करते हैं:

targetServer.js:

var https = require('https');
var fs = require('fs');

var options = {
    key: fs.readFileSync('./certs2/key.pem'),
    cert: fs.readFileSync('./certs2/key-cert.pem')
};

https.createServer(options, function (req, res) {
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
    res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
    res.writeHead(200);
    res.end("hello world\n");
}).listen(8001);

applicationServer.js:

var https = require('https');
var fs = require('fs');

var options = {
    key: fs.readFileSync('./certs/key.pem'),
    cert: fs.readFileSync('./certs/key-cert.pem')
};

https.createServer(options, function (req, res) {
    res.writeHead(200);
    res.end("hello world\n");
}).listen(8000);

यह काम करने के लिए आपको Nodejs इंस्टॉल करने की आवश्यकता होती है, प्रत्येक सर्वर के लिए अलग प्रमाण पत्र बनाने और उसके अनुसार फ़ोल्डरों के सिरे और certs2 में स्टोर करने की आवश्यकता होती है।

इसे चलाने के लिए बस निष्पादित करें node applicationServer.jsऔर node targetServer.jsएक टर्मिनल (ubuntu उदाहरण) में।


6
यह अब तक का सबसे पूर्ण जवाब है। यह दर्शाता है कि आपने वास्तव में कुछ शोध कार्य और परीक्षण किए हैं। मैं देखता हूं कि आपने इसे करने के लिए हर संभव कोशिश की है और सभी परिदृश्यों को वास्तव में अच्छी तरह से समझाया गया है। आपने जल्दी से एक परीक्षण वातावरण स्थापित करने के लिए उदाहरण कोड भी प्रदान किया है! वास्तव में अच्छा काम! अंतर्दृष्टि के लिए धन्यवाद!
13

बहुत बढ़िया जवाब! हालाँकि मैं यह बताना चाहूंगा कि स्व-हस्ताक्षरित प्रमाणपत्र अभी भी एक ब्राउज़र से त्रुटियों को पैदा करेगा यदि वे अलग-अलग सर्वर से हैं। @ecarrizo
फैब्रिकियो

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

32

अब तक: इस घटना को ब्राउजर के बीच अंतर करने का कोई तरीका नहीं है। चूंकि ब्राउज़र डेवलपर्स को एक्सेस करने के लिए कोई ईवेंट प्रदान नहीं करते हैं।(जुलाई 2015)

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


अस्वीकरण: यह उत्तर अधूरा है क्योंकि यह ओपी के मुद्दों (क्रॉस-मूल नीतियों के कारण) को पूरी तरह से हल नहीं करता है । हालाँकि इस विचार में स्वयं कुछ योग्यताएँ हैं जो आगे चलकर इस पर विस्तृत होती हैं: @artur grzesiak , एक प्रॉक्सी और अजाक्स का उपयोग करके।


अपने आप में काफी शोध के बाद, कनेक्शन से इनकार करने और असुरक्षित प्रतिक्रिया के बीच अंतर के लिए त्रुटि जाँच का कोई भी रूप प्रतीत नहीं होता, कम से कम जहाँ तक जावास्क्रिप्ट दोनों के बीच अंतर के लिए एक प्रतिक्रिया प्रदान करता है।

मेरे शोध की सामान्य सर्वसम्मति है कि एसएसएल प्रमाणपत्र ब्राउज़र द्वारा नियंत्रित किए जाते हैं, इसलिए जब तक उपयोगकर्ता द्वारा स्व-हस्ताक्षरित प्रमाणपत्र स्वीकार नहीं किया जाता है, तब तक ब्राउज़र सभी अनुरोधों को बंद कर देता है, जिनमें एक स्थिति कोड भी शामिल है। ब्राउज़र (यदि कोडित है) वापस भेज सकता है यह असुरक्षित प्रतिक्रिया के लिए स्वयं का स्थिति कोड है, लेकिन यह वास्तव में कुछ भी मदद नहीं करता है, और फिर भी, आपके पास ब्राउज़र संगतता (क्रोम / फ़ायरफ़ॉक्स / आईई) के साथ विभिन्न मानक होंगे। .. एक बार फिर)

चूँकि आपका मूल प्रश्न आपके सर्वर की स्थिति की जाँच करने के लिए था। एक अस्वीकार्य प्रमाणपत्र होने के बीच, क्या आप ऐसा मानक HTTP अनुरोध नहीं कर सकते थे?

isUp = false;
isAccepted = false;

var isUpRequest = new XMLHttpRequest();
isUpRequest.open('GET', "http://localhost/custom/server/", true); //note non-ssl port
isUpRequest.onload = function() {
    isUp = true;
    var isAcceptedRequest = new XMLHttpRequest();
    isAcceptedRequest.open('GET', "https://localhost/custom/server/", true); //note ssl port
    isAcceptedRequest.onload = function() {
        console.log("Server is up and certificate accepted");
        isAccepted = true;
    }
    isAcceptedRequest.onerror = function() {
        console.log("Server is up and certificate is not accepted");
    }
    isAcceptedRequest.send();
};
isUpRequest.onerror = function() {
    console.log("Server is down");
};
isUpRequest.send();

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


7
मैंने पूरा उत्तर पढ़ा है और मुझे नहीं लगता कि यह काम करेगा। दोनों मेरे सर्वर HTTPS चल रहे हैं, जिसका अर्थ है कि इस समय मैं एक HTTP सर्वर को एक अनुरोध आग, ब्राउज़र इसे तुरंत रद्द हो जाएगा, क्योंकि आप एक HTTP सर्वर के लिए एक HTTPS सर्वर से ajax अनुरोध नहीं कर सकते हैं
taxicala

11

@ शुल्त्ज़ी का जवाब बहुत करीब है, लेकिन स्पष्ट रूप से http- सामान्य रूप से - से काम नहीं चलेगाhttps ब्राउज़र वातावरण ।

हालाँकि आप अपनी ओर से अनुरोध करने के लिए एक मध्यवर्ती सर्वर (प्रॉक्सी) का उपयोग कर सकते हैं। प्रॉक्सी को या तो मूल httpअनुरोध को अग्रेषित करने httpsया स्व-हस्ताक्षरित मूल से सामग्री लोड करने की अनुमति देनी चाहिए

उचित प्रमाण पत्र के साथ आपका अपना सर्वर होना संभवतः आपके मामले में एक ओवरकिल है - जैसा कि आप स्व-हस्ताक्षरित प्रमाण पत्र के साथ मशीन के बजाय इस सेटिंग का उपयोग कर सकते हैं - लेकिन बहुत सारी अनाम खुली प्रॉक्सी सेवाएँ हैं हैं।

तो मेरे मन में आने वाले दो दृष्टिकोण हैं:

  1. अजाक्स अनुरोध - ऐसे मामले में प्रॉक्सी को उपयुक्त CORS सेटिंग्स का उपयोग करना पड़ता है
  2. एक iframe का उपयोग - आप प्रॉक्सी के माध्यम से एक iframe के अंदर अपनी स्क्रिप्ट (शायद HTML में लिपटे हुए) लोड करते हैं। एक बार स्क्रिप्ट लोड होने के बाद यह उसके लिए एक संदेश भेजता है .parentWindow। यदि आपकी विंडो को एक संदेश प्राप्त हुआ है तो आप सुनिश्चित कर सकते हैं कि सर्वर चल रहा है (या इससे अधिक सटीक रूप से दूसरे का एक अंश पहले चल रहा था)।

यदि आप केवल अपने स्थानीय परिवेश में रुचि रखते हैं तो आप --disable-web-securityध्वज के साथ क्रोम को चलाने का प्रयास कर सकते हैं ।


एक और सुझाव: क्या आपने यह पता लगाने के लिए किसी छवि को लोड करने की कोशिश की कि क्या अधिक जानकारी वहां मौजूद है?


1

की जाँच करें jQuery.ajaxError () से संदर्भ लिया गया: jQuery AJAX त्रुटि हैंडलिंग (HTTP स्थिति कोड) यह वैश्विक अजाक्स त्रुटियों जो आप HTTP या HTTPS पर किसी भी तरीके से में संभाल कर सकते हैं फैल जाती है:

if (jqXHR.status == 501) {
//insecure response
} else if (jqXHR.status == 102) {
//connection refused
}

यह ajax करने के तरीके के समान है जो मैं कर रहा हूं, लेकिन एक स्थान पर त्रुटि प्रतिक्रियाओं को केंद्रीकृत करना।
करियाला

1
मुद्दा यह है कि जब अजाक्स कॉल किया जाता है तो सर्टिफिकेट लोड नहीं किया जाता है क्योंकि यह समस्या लगती है। किसी भी तरह से जवाब खोजने के साथ gl :)
वर्षा

2
नहीं, समस्या यह है कि मैं प्रमाण पत्र को स्वीकार करने और सर्वर बंद होने पर जानने के बीच का अंतर निर्धारित करना चाहता हूं।
करिकला

1
जब कनेक्शन से इनकार कर दिया जाता है और प्रमाण पत्र पर भरोसा नहीं किया जाता है, तो मुझे इस उत्तर में वर्णित एक ही jqXHR.status = 0 (और jqXHR.readyState = 0) मिलता है, न कि qXHR.status == 102 या 501।
19

1

दुर्भाग्य से वर्तमान के ब्राउज़र एक्सएचआर एपीआई एक स्पष्ट संकेत प्रदान नहीं करता है कि जब ब्राउज़र "असुरक्षित प्रतिक्रिया" के कारण कनेक्ट करने से इनकार करता है, और यह भी कि यह वेबसाइट के HTTP / SSL प्रमाणपत्र पर भरोसा नहीं करता है।

लेकिन इस समस्या के आसपास तरीके हैं।

एक समाधान मैं यह निर्धारित करने के लिए आया था कि जब ब्राउज़र एचटीटीपी / एसएसएल प्रमाणपत्र पर भरोसा नहीं करता है, तो पहले यह पता लगाना होगा कि क्या एक्सएचआर त्रुटि हुई है ( error()उदाहरण के लिए jQuery कॉलबैक का उपयोग करके ), तो जांचें कि क्या XHR कॉल 'https' है : // 'URL, और फिर जांचें कि क्या XHR readyState0 है, जिसका अर्थ है कि XHR कनेक्शन भी नहीं खोला गया है (जो तब होता है जब ब्राउज़र को प्रमाणपत्र पसंद नहीं होता है)।

यहां वह कोड है जहां मैं यह करता हूं: https://github.com/maratbn/RainbowPayPress/blob/e9e9472a36ced747a0f9e5ca9fa7d96959aeafaa/rainbowpaypress/js/le_requirejs/public/model_info/tfo_tfo


1

मुझे नहीं लगता कि वर्तमान में इन त्रुटि संदेशों का पता लगाने का कोई तरीका है, लेकिन एक हैक जो आप कर सकते हैं वह है अपने एप्लिकेशन सर्वर के सामने nginx जैसे सर्वर का उपयोग करना, ताकि यदि एप्लिकेशन सर्वर नीचे है तो आपको खराब मिलेगा 502स्थिति कोड के साथ nginx से गेटवे त्रुटि जो आप जेएस में पता लगा सकते हैं। अन्यथा, यदि प्रमाणपत्र अमान्य है, तो आपको अभी भी वही सामान्य त्रुटि मिलेगी statusCode = 0

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