Przeprowadziłem wiele badań i nie mogłem znaleźć sposobu, aby sobie z tym poradzić. Próbuję wykonać wywołanie jQuery ajax z serwera https do lokalnego serwera https z uruchomionym pomostem z niestandardowym certyfikatem z podpisem własnym. Mój problem polega na tym, że nie mogę określić, czy odpowiedzią jest odmowa połączenia, czy odpowiedź niepewna (z powodu braku akceptacji certyfikatu). Czy istnieje sposób na określenie różnicy między obydwoma scenariuszami? Te responseText
, i statusCode
są zawsze takie same w obu przypadkach, mimo że w konsoli chrome widać różnicę:
net::ERR_INSECURE_RESPONSE
net::ERR_CONNECTION_REFUSED
responseText
jest zawsze „” i statusCode
zawsze wynosi „0” w obu przypadkach.
Moje pytanie brzmi, jak mogę określić, czy wywołanie jQuery ajax nie powiodło się z powodu ERR_INSECURE_RESPONSE
lub z powodu ERR_CONNECTION_REFUSED
?
Po zaakceptowaniu certyfikatu wszystko działa poprawnie, ale chcę wiedzieć, czy serwer localhost jest wyłączony, czy działa i działa, ale certyfikat nie został jeszcze zaakceptowany.
$.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.
}
});
Nawet wykonując żądanie ręcznie, otrzymuję ten sam wynik:
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();
źródło
function (xhr, status, msg) {...
Wątpię, że tak będzie, ale warto spróbować.Odpowiedzi:
Nie ma sposobu, aby odróżnić go od najnowszych przeglądarek internetowych.
Specyfikacja W3C:
Jak możesz przeczytać, błędy sieciowe nie obejmują odpowiedzi HTTP, które zawierają błędy, dlatego zawsze otrzymasz 0 jako kod statusu i "" jako błąd.
Źródło
Uwaga : Poniższe przykłady zostały wykonane przy użyciu przeglądarki Google Chrome w wersji 43.0.2357.130 i w środowisku, które stworzyłem, aby emulować OP one. Kod do konfiguracji znajduje się na dole odpowiedzi.
Myślałem, że podejście do obejścia tego byłoby wykonanie dodatkowego żądania przez HTTP zamiast HTTPS jako Ta odpowiedź, ale pamiętałem, że nie jest to możliwe, ponieważ nowsze wersje przeglądarek blokują mieszaną zawartość.
Oznacza to, że przeglądarka internetowa nie zezwoli na żądania za pośrednictwem protokołu HTTP, jeśli używasz protokołu HTTPS i odwrotnie.
Dzieje się tak od kilku lat, ale starsze wersje przeglądarek internetowych, takie jak Mozilla Firefox poniżej, wersje 23 pozwalają na to.
Dowody na to:
Wykonywanie żądania HTTP z HTTPS przy użyciu konsoli Web Broser
spowoduje następujący błąd:
Ten sam błąd pojawi się w konsoli przeglądarki, jeśli spróbujesz to zrobić w inny sposób, jak dodanie elementu iframe.
Używanie połączenia Socket zostało również opublikowane jako odpowiedź , byłem prawie pewien, że wynik będzie taki sam / podobny, ale spróbuję.
Próba otwarcia połączenia przez gniazdo z przeglądarki internetowej przy użyciu protokołu HTTPS do punktu końcowego niezabezpieczonego gniazda zakończy się błędami zawartości mieszanej.
Następnie próbowałem również połączyć się z punktem końcowym wss, zobacz Jeśli mogę przeczytać informacje o błędach połączenia sieciowego:
Wykonanie powyższego fragmentu z wyłączonym serwerem skutkuje:
Wykonywanie powyższego fragmentu z włączonym serwerem
Ale znowu, błąd, że "funkcja onerror" wyprowadzana do konsoli nie ma żadnej wskazówki, która pozwoliłaby odróżnić jeden błąd od drugiego.
Używanie proxy, jak sugeruje ta odpowiedź, może działać, ale tylko wtedy, gdy „docelowy” serwer ma dostęp publiczny.
W tym przypadku tak nie było, więc próba zaimplementowania serwera proxy w tym scenariuszu doprowadzi nas do tego samego problemu.
Kod do utworzenia serwera HTTPS Node.js :
Stworzyłem dwa serwery HTTPS Nodejs, które używają certyfikatów z podpisem własnym:
targetServer.js:
applicationServer.js:
Aby to działało, musisz mieć zainstalowany Nodejs, musisz wygenerować oddzielne certyfikaty dla każdego serwera i odpowiednio przechowywać go w folderach certs i certs2.
Aby go uruchomić wystarczy wykonać
node applicationServer.js
oraznode targetServer.js
w terminalu (np ubuntu).źródło
Od teraz: nie ma sposobu, aby odróżnić to wydarzenie między przeglądarkami. Ponieważ przeglądarki nie zapewniają dostępu programistom do zdarzeń. (Lipiec 2015)
Ta odpowiedź ma jedynie na celu przedstawienie pomysłów na potencjalne, choć niekompletne i niekompletne rozwiązanie.
Zastrzeżenie: ta odpowiedź jest niekompletna, ponieważ nie rozwiązuje całkowicie problemów OP (ze względu na zasady dotyczące różnych źródeł). Jednak sam pomysł ma pewne zalety , które są dalej rozwijane przez: @artur grzesiak tutaj , używając proxy i ajax.
Po wielu badaniach nie wydaje się, aby istniała żadna forma sprawdzania błędów pod kątem różnicy między odmową połączenia a niezabezpieczoną odpowiedzią, przynajmniej w zakresie, w jakim javascript zapewnia odpowiedź na różnicę między nimi.
Ogólny konsensus moich badań jest taki, że certyfikaty SSL są obsługiwane przez przeglądarkę, więc dopóki sam certyfikat z podpisem nie zostanie zaakceptowany przez użytkownika, przeglądarka blokuje wszystkie żądania, w tym te dotyczące kodu stanu. Przeglądarka mogłaby (jeśli została zakodowana) odesłać swój własny kod stanu dla niezabezpieczonej odpowiedzi, ale to tak naprawdę nic nie pomaga, a nawet wtedy miałbyś problemy z kompatybilnością przeglądarki (chrome / firefox / IE mają różne standardy. .. jeszcze raz)
Ponieważ Twoje pierwotne pytanie dotyczyło sprawdzenia stanu serwera między działaniem a posiadaniem nieakceptowanego certyfikatu, czy nie mógłbyś wysłać standardowego żądania HTTP?
To prawda, że wymaga to dodatkowego żądania w celu zweryfikowania łączności z serwerem, ale powinno to wykonać proces eliminacji. Nadal jednak czuję się zepsuty i nie jestem wielkim fanem podwójnej prośby.
źródło
Odpowiedź @ Schultzie jest dość bliska, ale wyraźnie
http
- ogólnie - nie będzie działaćhttps
w środowisku przeglądarki.Możesz jednak skorzystać z serwera pośredniego (proxy), aby wysłać żądanie w Twoim imieniu. Serwer proxy powinien umożliwiać przekazywanie
http
żądań zehttps
źródła lub ładowanie treści z źródeł z podpisem własnym .Posiadanie własnego serwera z odpowiednim certyfikatem jest prawdopodobnie przesadą w twoim przypadku - ponieważ możesz użyć tego ustawienia zamiast maszyny z certyfikatem z podpisem własnym - ale istnieje wiele anonimowych otwartych usług proxy .
Tak więc przychodzą mi do głowy dwa podejścia:
.parentWindow
. Jeśli twoje okno otrzymało wiadomość, możesz być pewien, że serwer jest uruchomiony (a dokładniej działał ułamek sekundy wcześniej).Jeśli interesuje Cię tylko lokalne środowisko, możesz spróbować uruchomić chrome z
--disable-web-security
flagą.Kolejna sugestia: czy próbowałeś załadować obraz programowo, aby dowiedzieć się, czy jest tam więcej informacji?
źródło
Sprawdź jQuery.ajaxError () Odniesienie z: jQuery AJAX Error Handling (HTTP Status Codes) Przechwytuje globalne błędy Ajax, które możesz obsłużyć na wiele sposobów przez HTTP lub HTTPS:
źródło
Niestety, dzisiejszy interfejs API XHR przeglądarki nie podaje wyraźnego wskazania, kiedy przeglądarka odmawia połączenia z powodu „niezabezpieczonej odpowiedzi”, a także kiedy nie ufa certyfikatowi HTTP / SSL witryny.
Ale są sposoby na obejście tego problemu.
Jednym z rozwiązań, które wymyśliłem, aby określić, kiedy przeglądarka nie ufa certyfikatowi HTTP / SSL, polega na pierwszym wykryciu, czy wystąpił błąd XHR (
error()
na przykład przy użyciu wywołania zwrotnego jQuery ), a następnie sprawdzenie, czy wywołanie XHR jest skierowane do 'https : // '', a następnie sprawdź, czy XHRreadyState
ma wartość 0, co oznacza, że połączenie XHR nie zostało nawet otwarte (co się dzieje, gdy przeglądarka nie polubi certyfikatu).Oto kod, w którym to robię: https://github.com/maratbn/RainbowPayPress/blob/e9e9472a36ced747a0f9e5ca9fa7d96959aeaf8a/rainbowpaypress/js/le_requirejs/public/model_info__transaction_details.js
źródło
Nie sądzę, aby obecnie istniał sposób na wykrycie tych komunikatów o błędach, ale sztuczka, którą możesz zrobić, to użyć serwera takiego jak nginx przed serwerem aplikacji, więc jeśli serwer aplikacji nie działa, otrzymasz zły błąd bramy z nginx z
502
kodem statusu, który można wykryć w JS. W przeciwnym razie, jeśli certyfikat jest nieważny, nadal będziesz otrzymywać ten sam błąd ogólny zstatusCode = 0
.źródło