我已经做了很多研究,但找不到处理这个问题的方法。我正在尝试执行jQuery ajax调用,从https服务器调用运行jetty的locahost https服务器,并使用自定义自签名证书。我的问题是,我无法确定响应是连接被拒绝还是不安全的响应(由于缺乏证书接受)。有没有办法确定两种情况之间的差异?在这两种情况下,responseText和statusCode始终是相同的,尽管在chrome控制台中我可以看到不同:
net::ERR\u unsecure\u响应
网络::错误连接被拒绝
对于这两种情况,responseText始终为“”,而statusCode始终为“0”
我的问题是,如何确定jQuery ajax调用是由于ERR\u unsecure\u响应还是由于ERR\u连接被拒绝
一旦证书被接受,一切正常,但我想知道本地主机服务器是关闭了,还是启动并运行了,但证书尚未被接受
$.ajax({
键入:“GET”,
url:“https://localhost/custom/server/",
数据类型:“json”,
async:true,
成功:功能(响应){
//做点什么
},
错误:函数(xhr、textStatus、errorshown){
log(xhr,textStatus,errorshorn);//对于被拒绝和不安全的响应总是相同的。
}
});
即使手动执行请求,我也会得到相同的结果:
var请求=新的XMLHttpRequest();
request.open('GET',”https://localhost/custom/server/“,对);
request.onload=函数(){
console.log(request.responseText);
};
request.onerror=函数(){
console.log(request.responseText);
};
request.send();
没有办法将它与最新的Web浏览器区分开来
W3C规范:
以下步骤描述了用户代理必须为简单的跨源请求执行的操作:
在提出请求时,应用“提出请求”步骤并遵守以下请求规则
如果手动重定向标志未设置且响应的HTTP状态代码为301、302、303、307或308
应用重定向步骤如果最终用户取消请求
应用中止步骤如果出现网络错误
如果出现DNS错误、TLS协商失败或其他类型的网络错误,请应用网络错误步骤。不要请求任何类型的最终用户交互注意:这不包括指示某种类型错误的HTTP响应,例如HTTP状态代码410。
否则
执行资源共享检查。如果返回fail,则应用网络错误步骤。否则,如果返回pass,则终止此算法并将跨源请求状态设置为success。不要实际终止请求
如您所知,网络错误不包括包含错误的HTTP响应,这就是为什么您总是将0作为状态代码,将“”作为错误。
来源
注意:以下示例是使用Google Chrome 43.0.2357.130版制作的,并且是针对我为模拟OP one而创建的环境制作的。设置它的代码位于答案的底部
我认为解决这个问题的一种方法是通过HTTP而不是HTTPS发出第二个请求作为答案,但我记得这是不可能的,因为较新版本的浏览器会阻止混合内容
这意味着如果您使用HTTPS,Web浏览器将不允许通过HTTP进行请求,反之亦然
几年前就一直如此,但较旧的网络浏览器版本,如Mozilla Firefox低于it版本23,允许这样做
关于它的证据:
从HTTPS usign Web Broser控制台发出HTTP请求
var请求=新的XMLHttpRequest();
request.open('GET',”http://localhost:8001“,对);
request.onload=函数(){
console.log(request.responseText);
};
request.onerror=函数(){
console.log(request.responseText);
};
request.send();
将导致以下错误:
混合内容:页面位于’https://localhost:8000/’已通过HTTPS加载,但请求了不安全的XMLHttpRequest终结点’http://localhost:8001/’. 此请求已被阻止;内容必须通过HTTPS提供
如果您尝试以添加Iframe的其他方式执行此操作,浏览器控制台中将出现相同的错误
<;iframe src=”http://localhost:8001“></iframe>;
使用套接字连接也是一个答案,我很确定结果会是相同/相似的,但我已经尝试过了
尝试使用HTTPS打开从Web浏览器到非安全套接字端点的套接字连接将导致混合内容错误
新WebSocket(“ws://localhost:8001”,“protocolOne”);
1) 混合内容:页面位于’https://localhost:8000/’已通过HTTPS加载,但尝试连接到不安全的WebSocket终结点’ws://localhost:8001/’。此请求已被阻止;此端点必须在WSS上可用
2) 未捕获的DomeException:构造“WebSocket”失败:可能无法从通过HTTPS加载的页面启动不安全的WebSocket连接
然后,我也尝试连接到wss端点,看看是否可以阅读有关网络连接错误的信息:
var exampleSocket=新的WebSocket(“wss://localhost:8001“,“原科隆”);
exampleSocket.onerror=函数(e){
控制台日志(e);
}
在服务器关闭的情况下执行上述代码段会导致:
WebSocket连接到’wss://localhost:8001/’失败:建立连接时出错:网络::错误\u连接\u被拒绝
在服务器打开的情况下执行上面的代码段
WebSocket连接到’wss://localhost:8001/’失败:WebSocket打开握手已取消
但同样,控制台的“onerror函数”输出没有任何提示来区分一个错误和另一个错误
这个答案表明,使用代理可能有效,但前提是“目标”服务器具有公共访问权限
这里的情况并非如此,因此在这种情况下尝试实现代理将导致我们遇到同样的问题
创建Node.js HTTPS服务器的代码:
我创建了两个使用自签名证书的Nodejs HTTPS服务器:
targetServer.js:
var https=require('https');
var fs=需要('fs');
变量选项={
key:fs.readFileSync('./certs2/key.pem'),
证书:fs.readFileSync('./certs2/key-cert.pem')
};
https.createServer(选项、功能(请求、恢复){
res.setHeader('Access-Control-Allow-Origin','*');
res.setHeader('Access-Control-Allow-Methods','GET、PUT、POST、DELETE');
res.setHeader('Access-Control-Allow-Headers','Content-Type');
书面记录(200);
res.end(“hello world\n”);
}).听(8001);
applicationServer.js:
var https=require('https');
var fs=需要('fs');
变量选项={
key:fs.readFileSync('./certs/key.pem'),
证书:fs.readFileSync('./certs/key-cert.pem')
};
https.createServer(选项、功能(请求、恢复){
书面记录(200);
res.end(“hello world\n”);
}).听(8000);
要使其正常工作,您需要安装NodeJ,需要为每个服务器生成单独的证书,并相应地将其存储在文件夹certs和certs2中
要运行它,只需在终端中执行节点applicationServer.js和节点targetServer.js(ubuntu示例)