나는 많은 연구를 해왔고 이것을 처리 할 방법을 찾지 못했습니다. https 서버에서 사용자 정의 자체 서명 인증서로 부두를 실행하는 locahost https 서버로 jQuery ajax 호출을 수행하려고합니다. 내 문제는 응답이 연결이 거부되었는지 아니면 안전하지 않은 응답인지 확인할 수 없다는 것입니다 (인증서 수락 부족으로 인해). 두 시나리오의 차이점을 확인하는 방법이 있습니까? responseText
, 그리고 statusCode
크롬 콘솔에서 나는 차이를 볼 수 있지만, 항상 두 경우 모두 동일합니다 :
net::ERR_INSECURE_RESPONSE
net::ERR_CONNECTION_REFUSED
responseText
statusCode
두 경우 모두 항상 “”이고 항상 “0”입니다.
JQuery와 아약스 호출로 인해 실패 할 경우 내 질문은, 어떻게 판단 할 수있다 ERR_INSECURE_RESPONSE
또는 때문에 ERR_CONNECTION_REFUSED
?
인증서가 수락되면 모든 것이 정상적으로 작동하지만 localhost 서버가 종료되었는지 또는 실행 중이지만 인증서가 아직 수락되지 않았는지 알고 싶습니다.
$.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();
답변
최신 웹 브라우저와 구별 할 방법이 없습니다.
W3C 사양 :
아래 단계는 간단한 교차 출처 요청에 대해 사용자 에이전트가 수행해야하는 작업을 설명합니다 .
요청하기 단계를 적용하고 요청하는 동안 아래 요청 규칙을 준수하십시오.
수동 리디렉션 플래그가 설정되어 있지 않고 응답에 301, 302, 303, 307 또는 308의 HTTP 상태 코드가있는
경우 리디렉션 단계를 적용합니다.최종 사용자가 요청을 취소하는 경우
중단 단계를 적용합니다.네트워크 오류가있는
경우 DNS 오류, TLS 협상 실패 또는 기타 유형의 네트워크 오류가있는 경우 네트워크 오류 단계를 적용 합니다 . 어떠한 종류의 최종 사용자 상호 작용도 요청하지 마십시오.참고 : 여기에는 HTTP 상태 코드 410과 같은 오류 유형을 나타내는 HTTP 응답이 포함되지 않습니다.
그렇지 않으면
자원 공유 검사를 수행하십시오. 실패하면 네트워크 오류 단계를 적용하십시오. 그렇지 않고 통과를 반환하면이 알고리즘을 종료하고 교차 출처 요청 상태를 성공으로 설정합니다. 실제로 요청을 종료하지 마십시오.
읽을 수 있듯이 네트워크 오류에는 오류가 포함 된 HTTP 응답이 포함되지 않으므로 항상 상태 코드로 0, 오류로 “”가 표시됩니다.
참고 : 다음 예제는 Google Chrome 버전 43.0.2357.130을 사용하고 OP 1을 에뮬레이션하기 위해 만든 환경에 대해 작성되었습니다. 설정 코드는 답변 하단에 있습니다.
나는이 문제를 해결하기 위해이 답변 으로 HTTPS 대신 HTTP를 통해 보조 요청을하는 것이지만 새로운 버전의 브라우저가 혼합 콘텐츠를 차단하기 때문에 불가능하다는 것을 기억했습니다.
즉, HTTPS를 사용하는 경우 웹 브라우저가 HTTP를 통한 요청을 허용하지 않으며 그 반대의 경우도 마찬가지입니다.
이것은 몇 년 전부터 이와 같았지만 Mozilla Firefox와 같은 이전 웹 브라우저 버전은 23 버전 이하에서 허용됩니다.
그것에 대한 증거 :
Web Broser 콘솔을 사용하여 HTTPS에서 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 : // localhost : 8000 / ‘의 페이지가 HTTPS를 통해로드되었지만 안전하지 않은 XMLHttpRequest 엔드 포인트 ‘ http : // localhost : 8001 / ‘를 요청했습니다. 이 요청은 차단되었습니다. 콘텐츠는 HTTPS를 통해 제공되어야합니다.
Iframe을 추가하는 것과 같은 다른 방법으로이 작업을 시도하면 브라우저 콘솔에 동일한 오류가 나타납니다.
<iframe src="http://localhost:8001"></iframe>
소켓 연결을 사용 하여 답변으로 게시 했습니다. 결과가 동일 / 유사 할 것이라고 확신했지만 시도해 보았습니다.
HTTPS를 사용하여 웹 브라우저에서 비보안 소켓 끝점으로 소켓 연결을 열려고하면 혼합 콘텐츠 오류가 발생합니다.
new WebSocket("ws://localhost:8001", "protocolOne");
1) 혼합 콘텐츠 : ‘ https : // localhost : 8000 / ‘의 페이지가 HTTPS를 통해로드되었지만 안전하지 않은 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);
}
서버를 끈 상태에서 위의 스 니펫을 실행하면 다음과 같은 결과가 발생합니다.
‘wss : // localhost : 8001 /’에 대한 WebSocket 연결 실패 : 연결 설정 오류 : net :: ERR_CONNECTION_REFUSED
서버를 켠 상태에서 위의 스 니펫 실행
‘wss : // localhost : 8001 /’에 대한 WebSocket 연결 실패 : WebSocket 열기 핸드 셰이크가 취소되었습니다.
그러나 다시 말하지만, “onerror function”이 콘솔에 출력하는 오류는 하나의 오류를 다른 오류를 구별하는 팁이 없습니다.
이 답변이 제안한 대로 프록시를 사용 하면 “대상”서버에 공용 액세스 권한이있는 경우에만 작동 할 수 있습니다.
여기에서는 그렇지 않았으므로이 시나리오에서 프록시를 구현하려고하면 동일한 문제가 발생합니다.
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를 설치해야합니다. 각 서버에 대해 별도의 인증서를 생성하고 그에 따라 certs 및 certs2 폴더에 저장해야합니다.
실행하는 단지 실행 node applicationServer.js
하고 node targetServer.js
단말기 (우분투 예)이다.
답변
현재 : 브라우저간에이 이벤트를 구분할 수있는 방법이 없습니다. 브라우저는 개발자가 액세스 할 수있는 이벤트를 제공하지 않습니다. (2015 년 7 월)
이 답변은 잠재적이고 해키스럽고 불완전한 솔루션에 대한 아이디어를 제공하기위한 것입니다.
면책 조항 : 이 답변은 OP 문제를 완전히 해결 하지 못 하기 때문에 불완전 합니다 (교차 출처 정책으로 인해). 그러나 아이디어 자체에는 프록시와 ajax를 사용하여 @artur grzesiak here 에서 추가로 확장되는 몇 가지 장점이 있습니다.
꽤 많은 연구 끝에 연결 거부와 안전하지 않은 응답 사이의 차이를 확인하는 오류가없는 것 같습니다. 적어도 둘 사이의 차이에 대한 응답을 제공하는 자바 스크립트에 한합니다.
내 연구에 대한 일반적인 합의는 SSL 인증서가 브라우저에 의해 처리되므로 사용자가 자체 서명 된 인증서를 수락 할 때까지 브라우저는 상태 코드에 대한 요청을 포함하여 모든 요청을 잠급니다. 브라우저는 (코딩 된 경우) 안전하지 않은 응답에 대해 자체 상태 코드를 다시 보낼 수 있지만 실제로는 도움이되지 않으며 브라우저 호환성 (다른 표준을 갖는 크롬 / 파이어 폭스 / IE)에 문제가있을 수 있습니다. .. 다시 한번)
원래 질문은 서버가 작동 중인지 아니면 허용되지 않는 인증서가 있는지 확인하는 것이었기 때문에 이와 같은 표준 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();
이 경우 서버 연결을 확인하기위한 추가 요청이 필요하지만 제거 프로세스를 통해 작업을 완료해야합니다. 그래도 여전히 엉뚱한 느낌이 들며 나는 두 배로 늘어난 요청을 좋아하지 않습니다.
답변
@Schultzie의 답변은 매우 비슷하지만 http
일반적으로 https
브라우저 환경 에서는 작동하지 않습니다 .
하지만 할 수있는 일은 중간 서버 (프록시)를 사용하여 대신 요청하는 것입니다. 프록시는 원본 http
에서 요청 을 전달 https
하거나 자체 서명 된 원본 에서 콘텐츠를로드 하도록 허용해야합니다 .
자체 서명 된 인증서가있는 컴퓨터 대신이 설정을 사용할 수 있기 때문에 적절한 인증서가있는 자체 서버를 보유하는 것은 아마도 과잉 일 것입니다.하지만 익명의 공개 프록시 서비스 가 많이 있습니다.
제 마음에 떠오르는 두 가지 접근 방식은 다음과 같습니다.
- ajax 요청 -이 경우 프록시는 적절한 CORS 설정을 사용해야합니다.
- iframe 사용 -프록시를 통해 iframe 내에서 스크립트 (아마도 html로 래핑 됨)를로드합니다. 스크립트가로드되면
.parentWindow
. 창에 메시지가 수신되면 서버가 실행 중인지 (또는 더 정확하게는 몇 초 전에 실행 중인지) 확인할 수 있습니다.
로컬 환경에만 관심이 있다면 --disable-web-security
플래그로 크롬을 실행할 수 있습니다 .
또 다른 제안 : 더 많은 정보가 있는지 알아보기 위해 이미지를 프로그래밍 방식으로로드하려고 했습니까?
답변
체크 아웃 jQuery.ajaxError을 ()
에서 참조를 촬영 : jQuery를 AJAX 오류 처리 (HTTP 상태 코드)
그것은 당신이 HTTP 또는 HTTPS를 통해 임의의 방식으로 처리 할 수있는 글로벌 아약스 오류를 잡아 :
if (jqXHR.status == 501) {
//insecure response
} else if (jqXHR.status == 102) {
//connection refused
}
답변
안타깝게도 현재의 브라우저 XHR API는 “안전하지 않은 응답”으로 인해 브라우저가 연결을 거부하는시기와 웹 사이트의 HTTP / SSL 인증서를 신뢰하지 않는시기에 대한 명시적인 표시를 제공하지 않습니다.
그러나이 문제를 해결하는 방법이 있습니다.
브라우저가 HTTP / SSL 인증서를 신뢰하지 않는시기를 확인하기 위해 내놓은 한 가지 해결책은 먼저 XHR 오류가 발생했는지 ( error()
예 : jQuery 콜백 사용) 감지 한 다음 XHR 호출이 ‘https’에 대한 것인지 확인하는 것입니다. : // ‘URL을 입력 한 다음 XHR readyState
이 0 인지 확인합니다. 이는 XHR 연결이 열리지 않았 음을 의미합니다 (브라우저가 인증서를 좋아하지 않을 때 발생 함).
이 작업을 수행하는 코드는 다음과 같습니다.
https://github.com/maratbn/RainbowPayPress/blob/e9e9472a36ced747a0f9e5ca9fa7d96959aeaf8a/rainbowpaypress/js/le_requirejs/public/model_info__transaction_details.js#L88
답변
현재 이러한 오류 메시지를 감지 할 수있는 방법은 없다고 생각합니다.하지만 할 수있는 방법은 응용 프로그램 서버 앞에 nginx와 같은 서버를 사용하는 것이므로 응용 프로그램 서버가 다운되면 문제가 발생할 수 있습니다. 502
JS에서 감지 할 수있는 상태 코드가있는 nginx의 게이트웨이 오류 . 그렇지 않으면 인증서가 유효하지 않은 경우에도 동일한 일반 오류가 발생합니다 statusCode = 0
.