"Contenuto misto bloccato" quando si esegue un'operazione HTTP AJAX in una pagina HTTPS


108

Ho un modulo che sto inviando (tramite GET in quanto è richiesto in questo modo) a un crm (ViciDial). Posso inviare correttamente il modulo, tuttavia, se lo faccio, il file di elaborazione su crm farà semplicemente eco un testo di successo e il gioco è fatto.

Invece di quel testo, voglio visualizzare una pagina di ringraziamento sul mio sito Web, quindi ho deciso di utilizzare AJAX per inviare il modulo e reindirizzarlo alla pagina di cui ho bisogno, tuttavia ricevo questo errore sul mio browser:

Contenuto misto: la pagina " https://page.com " è stata caricata tramite HTTPS, ma ha richiesto un endpoint XMLHttpRequest non sicuro " http://XX.XXX.XX.XXX/vicidial/non_agent_api.php?queries=query=data '. Questa richiesta è stata bloccata; il contenuto deve essere offerto tramite HTTPS.

Questo è il mio script AJAX:

    <script>
    SubmitFormClickToCall = function(){

        jQuery.ajax({
            url: "http://XX.XXX.XX.XX/vicidial/non_agent_api.php",
            data : jQuery("#form-click-to-call").serialize(),
            type : "GET",
            processData: false,
            contentType: false,
            success: function(data){
                window.location.href = "https://www.example.com/thank-you";
            }
        });
    }
    </script>

La semplice impostazione di https nell'URL non funzionerà, esiste un modo in cui posso inviare i dati tramite GET e reindirizzare l'utente alla mia pagina di ringraziamento?

============================

Il problema qui era contenuto misto, questo significa che ho caricato una pagina tramite HTTPS e stavo cercando di colpire tramite AJAX un'API che era in HTTP. Ma il browser non ci consentirà di farlo.

Quindi, se non è possibile impostare l'API su HTTPS (questo era il mio caso), possiamo comunque affrontarlo in un modo diverso.

Il problema principale non era il problema del contenuto misto, era che volevo inviare i dati a un'API e reindirizzare gli utenti a una pagina di ringraziamento di fantasia. Invece di usare AJAX, ho creato un file php che riceve i dati e li invia usando curl all'API (poiché questo viene fatto lato server non ci sono problemi di contenuto misto) e reindirizza il mio utente felice a una pagina di ringraziamento fantasia.


Hai una versione sicura della tua API? Dovrai richiedere tramite HTTPS se utilizzi un sito protetto come origine.
Cameron Tinker

1
No, non lo faccio, c'è qualche altro modo in cui potrei farlo? Voglio dire che la richiesta va a buon fine se usi il modulo di invio senza Ajax
StormRage

È possibile creare un URL HTTPS in Apache per il proxy XX.XXX.XX.XXsu HTTP. Tuttavia, se lo scopo di HTTP è proteggere le informazioni dell'utente, sarà necessario fare attenzione che il percorso tra i server non avvenga sulla rete Internet pubblica.
halfer

Risposte:


89

Se carichi una pagina nel tuo browser usando HTTPS, il browser rifiuterà di caricare qualsiasi risorsa su HTTP. Come hai provato, la modifica dell'URL dell'API per avere HTTPS anziché HTTP risolve in genere questo problema . Tuttavia, la tua API non deve consentire le connessioni HTTPS. Per questo motivo, è necessario forzare HTTP nella pagina principale o richiedere che consentano le connessioni HTTPS.

Nota su questo: la richiesta continuerà a funzionare se vai all'URL dell'API invece di tentare di caricarlo con AJAX. Questo perché il browser non sta caricando una risorsa da una pagina protetta, invece sta caricando una pagina non sicura e la sta accettando. Affinché sia ​​disponibile tramite AJAX, tuttavia, i protocolli dovrebbero corrispondere.


1
OK, l'API è nel mio server, c'è qualche guida che posso seguire per renderlo https?
StormRage

1
@StormRage Assolutamente! Che tipo di server stai utilizzando? Apache? È un hosting condiviso o un server privato?
Mikel Bitson

@StormRage Per favore fatemi sapere se avete bisogno di ulteriore assistenza. Altrimenti, il voto incentiverà l'assistenza pubblica che ottieni qui su SO.
Mikel Bitson

1
Scusa per il ritardo, sono riuscito a risolverlo senza usare AJAX, le mie soluzioni includono alcune funzioni wordpress / php curl, malato la mia soluzione il prima possibile, dovrei solo modificare la mia domanda e scrivere la mia soluzione in essa, o dovrei usare il pulsante che dice "rispondi alla tua domanda"?
StormRage

1
Ha evidenziato la parte rilevante della risposta qui. L'unica soluzione pratica a questo è usare HTTPS
Liam

130

Ho risolto questo problema aggiungendo il seguente codice alla pagina HTML, poiché stiamo utilizzando l'API di terze parti che non è controllata da noi.

<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests"> 

Spero che questo possa aiutare, e anche per la cronaca.


8
Questo aggiorna tutte le httprichieste da utilizzare https, quindi non è necessario modificare il protocollo per ogni chiamata.
entro il

3
Questo ha funzionato per me, ma sfortunatamente non funziona con Internet Explorer: developer.mozilla.org/en-US/docs/Web/HTTP/Headers/…
Ciaran Gallagher

2
Ho provato questo ma ora ricevo l'errore CORS su Firefox e net :: ERR_SSL_PROTOCOL_ERROR su Chrome. so che tutte le chiamate funzionano perché la mia pagina web prima era http, ma ora che sono passato a https queste chiamate non funzionano. c'è qualcos'altro che posso aggiungere al mio file html principale? Perché se seguo i passaggi di @Juanma Menendez tutte le chiamate funzionano ma non posso aspettarmi che ogni utente lo faccia.
Otorrinolaringologista -uomo

Ho lottato con questo problema per ore finché non ho trovato la tua risposta, grazie mille!
Muhab

Confermiamo che questa soluzione funziona sul nostro caso, forse forse aiuterà anche te in futuro: abbiamo provato a stabilire una funzionalità di live streaming / video on demand HTTP segmentata, qualcosa di simile www.example.com/blabla/master.m3u8. Ha funzionato tutto bene su http. Ma quando lo migriamo su https non funzionerà. Abbiamo scoperto che l'iniziale master.m3u8era in grado di fare httpsrichiesta, ma il seguente pezzo segmentato di video veniva sempre utilizzato http(perché stiamo usando un modulo di terze parti). Non importa cosa modifichiamo, semplicemente non lo useremo https. Utilizzato questa politica e ha funzionato immediatamente come un fascino!
rahmatns

34

Se stai solo visitando una pagina web di cui ti fidi e vuoi andare avanti velocemente, basta:

1- Fare clic sull'icona dello scudo all'estrema destra della barra degli indirizzi.

Consenti contenuti misti in Google Chrome

2- Nella finestra pop-up, fai clic su "Carica comunque" o "Carica script non sicuro" (a seconda della versione di Chrome).


Se desideri impostare il browser Chrome su SEMPRE (in tutte le pagine web) consenti contenuti misti:

1- In un browser Chrome aperto, premi Ctrl + Maiusc + Q sulla tastiera per forzare la chiusura di Chrome. Chrome deve essere completamente chiuso prima dei passaggi successivi.

2- Fare clic con il pulsante destro del mouse sull'icona di Google Chrome sul desktop (o sul collegamento del menu Start). Seleziona Proprietà.

3- Alla fine delle informazioni esistenti nel campo Target, aggiungi: "--allow-running-insecure-content" (C'è uno spazio prima del primo trattino.)

4- Fare clic su OK.

5- Apri Chrome e prova ad avviare il contenuto che è stato bloccato in precedenza. Ora dovrebbe funzionare.


4
Questo non fa nulla per le persone che progettano siti Web per quegli utenti che non vogliono modificare le proprie impostazioni per far funzionare il sito sul proprio browser, ad esempio l'OP.
smallpants

12

Il motivo di questo errore è molto semplice. Il tuo AJAX sta tentando di chiamare su HTTP mentre il tuo server è in esecuzione su HTTPS, quindi il tuo server sta negando di chiamare il tuo AJAX. Questo può essere risolto aggiungendo la seguente riga all'interno del tag head del tuo file HTML principale:

<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests"> 

lo consente ma la richiesta è https
BG BRUNO

Nel mio caso. solo la richiesta HTTP del server. Provo questo <meta> non può funzionare. Il browser dice errore di richiesta all'URL.
avevo 169 il

1

Se il tuo codice API è in esecuzione su un server node.js , devi concentrare la tua attenzione lì, non in Apache o NGINX. Mikel ha ragione, cambiare l'URL dell'API in HTTPS è la risposta, ma se la tua API sta chiamando un server node.js, è meglio che sia impostato per HTTPS! E, naturalmente, il server node.js può trovarsi su qualsiasi porta inutilizzata, non deve essere la porta 443.


L'API era di terze parti, quindi non era possibile impostarla su https e, come puoi vedere nell'URL che stavo cercando di
premere

@StormRage La tua domanda e la risposta di Mikel hanno portato a una soluzione per il mio problema, quindi ho pensato di prenderne nota qui anche se la mia risposta non si applica davvero alla tua situazione.
mcmacerson

Bene, tu e Mikel avete ragione, la soluzione più ragionevole sarebbe quella di utilizzare ssl nell'API, ma in questo contesto non sono stato in grado di farlo perché era un'API di terze parti, ma una soluzione per ppl che utilizza wordpress o qualsiasi sito legacy potrebbe inviare i dati al proprio backend e inviare la richiesta all'API all'interno del server.
StormRage

Ho implementato api da laravel come lato server e l'applicazione ionico come PWA sullo stesso host in modo che abbia lo stesso errore indicato in questo articolo stackoverflow.com/q/56157129/308578
sciabola Tabatabaee Yazdi

1

Invece di utilizzare il metodo Ajax Post, puoi utilizzare il modulo dinamico insieme all'elemento. Funzionerà anche se la pagina viene caricata in SSL e la fonte inviata non è SSL.

È necessario impostare il valore del valore dell'elemento del modulo.

In realtà il nuovo modulo dinamico si aprirà come modalità non SSL in una scheda separata del browser quando l'attributo target ha impostato "_blank"

var f = document.createElement('form');
f.action='http://XX.XXX.XX.XX/vicidial/non_agent_api.php';
f.method='POST';
//f.target='_blank';
//f.enctype="multipart/form-data"

var k=document.createElement('input');
k.type='hidden';k.name='CustomerID';
k.value='7299';
f.appendChild(k);



//var z=document.getElementById("FileNameId")
//z.setAttribute("name", "IDProof");
//z.setAttribute("id", "IDProof");
//f.appendChild(z);

document.body.appendChild(f);
f.submit()

In realtà voglio colpire un'API, ma quando lo faccio con il tuo metodo effettuando una richiesta di ricezione, in realtà invierei un modulo, ma ora sono bloccato con la lettura della risposta dall'API. Perché immagino che AJAX o xmlhttprequest sia l'unica opzione
Siddharth Choudhary

soluzione di intereting :-)
BG BRUNO

semplice e geniale
Harkal

0

Avevo lo stesso problema, ma per me il problema era ng build command. Stavo facendo "ng build --prod" l'ho corretto in "ng build --prod --base-href / applicationname /". e questo ha risolto il mio problema.


0

nel mio caso, il mio localhost era httpe la mia versione distribuita era https, quindi ho usato questo script per aggiungere il meta tag http-equiv solo per https:

if (window.location.protocol.indexOf('https') == 0){
  var el = document.createElement('meta')
  el.setAttribute('http-equiv', 'Content-Security-Policy')
  el.setAttribute('content', 'upgrade-insecure-requests')
  document.head.append(el)
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.