Nie ma sposobu, aby odróżnić go od najnowszych przeglądarek internetowych.
Specyfikacja W3C:
Poniższe kroki opisują, co muszą zrobić klienty użytkownika w przypadku prostego żądania z różnych źródeł :
Zastosuj kroki składania wniosku i przestrzegaj poniższych zasad podczas składania wniosku.
Jeśli flaga ręcznego przekierowania nie jest ustawiona, a odpowiedź ma kod stanu HTTP 301, 302, 303, 307 lub 308
Zastosuj kroki przekierowania.
Jeśli użytkownik końcowy anuluje żądanie,
zastosuj kroki przerwania.
Jeśli wystąpił błąd sieciowy
W przypadku błędów DNS, niepowodzenia negocjacji TLS lub innego rodzaju błędów sieciowych, zastosuj kroki błędu sieciowego . Nie żądaj żadnego rodzaju interakcji z użytkownikiem końcowym.
Uwaga: nie obejmuje to odpowiedzi HTTP wskazujących na jakiś rodzaj błędu, na przykład kod stanu HTTP 410.
W przeciwnym razie
Sprawdź udostępnianie zasobów. Jeśli zwróci błąd, zastosuj kroki dotyczące błędu sieci. W przeciwnym razie, jeśli zwróci pass, zakończ ten algorytm i ustaw stan żądania między źródłami na sukces. W rzeczywistości nie zamykaj żądania.
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
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();
spowoduje następujący błąd:
Zawartość mieszana: strona pod adresem „ https: // localhost: 8000 / ” została załadowana przez HTTPS, ale zażądała niezabezpieczonego punktu końcowego XMLHttpRequest „ http: // localhost: 8001 / ”. To żądanie zostało zablokowane; zawartość musi być dostarczana przez HTTPS.
Ten sam błąd pojawi się w konsoli przeglądarki, jeśli spróbujesz to zrobić w inny sposób, jak dodanie elementu iframe.
<iframe src="http://localhost:8001"></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.
new WebSocket("ws://localhost:8001", "protocolOne");
1) Zawartość mieszana: Strona pod adresem „ https: // localhost: 8000 / ” została załadowana przez HTTPS, ale próbowała połączyć się z niezabezpieczonym punktem końcowym WebSocket „ws: // localhost: 8001 /”. To żądanie zostało zablokowane; ten punkt końcowy musi być dostępny przez WSS.
2) Uncaught DOMException: nie udało się utworzyć „WebSocket”: niezabezpieczone połączenie WebSocket nie może zostać zainicjowane ze strony załadowanej przez HTTPS.
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:
var exampleSocket = new WebSocket("wss://localhost:8001", "protocolOne");
exampleSocket.onerror = function(e) {
console.log(e);
}
Wykonanie powyższego fragmentu z wyłączonym serwerem skutkuje:
Połączenie przez WebSocket z „wss: // localhost: 8001 /” nie powiodło się: Błąd podczas ustanawiania połączenia: net :: ERR_CONNECTION_REFUSED
Wykonywanie powyższego fragmentu z włączonym serwerem
Połączenie WebSocket z „wss: // localhost: 8001 /” nie powiodło się: anulowano uzgadnianie otwierania protokołu WebSocket
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:
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);
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
oraz node targetServer.js
w terminalu (np ubuntu).