I've been doing a lot of research and could not find a way to handle this. I'm trying to perform a jQuery ajax call from an https server to a locahost https server running jetty with a custom self signed certificate. My problem is that I cannot determine whether the response is a connection refused or a insecure response (due to the lack of the certificate acceptance). Is there a way to determine the difference between both scenarios? The responseText, and statusCode are always the same in both cases, even though in the chrome console I can see a difference:

net::ERR_INSECURE_RESPONSE
net::ERR_CONNECTION_REFUSED

responseText is always "" and statusCode is always "0" for both cases.

My question is, how can I determine if a jQuery ajax call failed due to ERR_INSECURE_RESPONSE or due to 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();

推荐答案

There is no way to differentiate it from newest Web Browsers.

W3C Specification:

The steps below describe what user agents must do for a simple cross-origin request:

Apply the make a request steps and observe the request rules below while making the request.

If the manual redirect flag is unset and the response has an HTTP status code of 301, 302, 303, 307, or 308个 应用重定向步骤.

If the end user cancels the request Apply the abort steps.

If there is a network error In case of DNS errors, TLS negotiation failure, or other type of network errors, apply the network error steps. Do not request any kind of end user interaction.

Note: This does not include HTTP responses that indicate some type of error, such as HTTP status code 410.

Otherwise个 执行资源共享判断.如果返回失败,请应用网络错误步骤.否则,如果返回PASS,则终止该算法,并将跨域请求状态设置为SUCCESS.请不要实际终止请求.

As you can read, network errors does not include HTTP response that include errors, that is why you will get always 0 as status code, and "" as error.

Source


Note: The following examples were made using Google Chrome Version 43.0.2357.130 and against an environment that I've created to emulate OP one. Code to the set it up is at the bottom of the answer.


I though that an approach To work around this would be make a secondary request over HTTP instead of HTTPS as This answer but I've remembered that is not possible due that newer versions of browsers block mixed content.

这意味着,如果您使用HTTPS,Web浏览器将不允许通过HTTP进行请求,反之亦然.

这在几年前就是这样了,但是更老的Web浏览器版本,如下面的Mozilla Firefox版本23允许这样做.

Evidence about it:

Making a HTTP request from HTTPS usign Web Broser console

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://localhost:8000/"处的页面是通过HTTPS加载的,但请求了不安全的XMLHttpRequest终结点"http://localhost:8001/".此请求已被阻止;内容必须通过HTTPS提供.

Same error will appear in the browser console if you try to do this in other ways as adding an Iframe.

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

使用Socket connection也是Posted as an answer,我很确定结果会相同/相似,但我已经try 过了.

Trying to Open a socket connection from the Web Broswer using HTTPS to a non Secure socket endpoint will end in mixed content errors.

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

1) 混合内容:"https://localhost:8000/"处的页面通过HTTPS加载,但试图连接到不安全的WebSocket端点"ws://localhost:8001/".此请求已被阻止;此端点必须通过WSS可用.

2) Uncaught DOMException: Failed to construct 'WebSocket': An insecure WebSocket connection may not be initiated from a page loaded over HTTPS.

然后,我也try 连接到wss端点,看看是否可以阅读有关网络连接错误的信息:

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

Executing snippet above with Server turned off results in:

到‘wss://localhost:8001/’的WebSocket连接失败:建立连接时出错:NET::ERR_CONNECTION_REJECTED

Executing snippet above with Server turned On

WebSocket connection to 'wss://localhost:8001/' failed: WebSocket opening handshake was canceled

But again, the error that the "onerror function" output to the console have not any tip to differentiate one error of the other.


使用代理as this answer suggest可以工作,但前提是"目标"服务器具有公共访问权限.

这里的情况并非如此,因此在这种情况下try 实现代理将导致我们遇到同样的问题.

Code to create Node.js HTTPS server:

我创建了两个使用自签名证书的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);

应用服务器.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,需要 for each 服务器生成单独的证书,并相应地将其存储在文件夹certs和certs2中.

To Run it just execute node applicationServer.js and node targetServer.js in a terminal (ubuntu example).

Jquery相关问答推荐

在 JQuery DataTable 中通过按钮单击传递 ID

在 jQuery 事件中控制this的值

如何使用 jQuery 禁用粘贴(Ctrl+V)?

元素上的 jQuery Change 事件 - 有什么方法可以保留以前的值?

jQuery 中的 $this 与 $(this)

jquery - 单击事件不适用于动态创建的按钮

动态设置 iframe src

lodash debounce 在匿名函数中不起作用

如何使用 jquery 正确格式化货币?

Onchange 通过 Select 打开 URL - jQuery

如何使用jQuery在弹出窗口中预览输入类型=文件中的选定图像?

如何通过 DOM 容器访问 Highcharts 图表?

带有 jquery.animate() 的 CSS 旋转跨浏览器

使用 Jquery 更改页面标题

如何使用 Twitter Bootstrap 自动关闭alert

javascript,是否有像 isArray 这样的 isObject 函数?

Jquery Select 所有具有 $jquery.data() 的元素

使用 TypeScript 设置 window.location

jquery追加到列表的前面/顶部

jquery ui Dialog:无法在初始化之前调用对话框上的方法