"Contenu mixte bloqué" lors de l'exécution d'une opération HTTP AJAX dans une page HTTPS

110

J'ai un formulaire que je soumets (via GET car il est requis de cette façon) à un crm (ViciDial). Je peux soumettre le formulaire avec succès, mais si je fais cela, le fichier de traitement au crm fera simplement écho à un texte de réussite et c'est tout.

Au lieu de ce texte, je souhaite afficher une page de remerciement sur mon site Web, j'ai donc décidé d'utiliser AJAX pour soumettre le formulaire et le rediriger vers la page dont j'ai besoin, mais j'obtiens cette erreur sur mon navigateur:

Contenu mixte: la page sur ' https://page.com ' a été chargée via HTTPS, mais a demandé un point de terminaison XMLHttpRequest non sécurisé ' http://XX.XXX.XX.XXX/vicidial/non_agent_api.php?queries=query=data ». Cette demande a été bloquée; le contenu doit être diffusé via HTTPS.

Voici mon 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>

Le simple fait de définir https dans l'URL ne fonctionnera pas, y a-t-il un moyen de soumettre les données via GET et de rediriger l'utilisateur vers ma page de remerciement?

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

Le problème ici était un contenu mixte, cela signifie que j'ai chargé une page via HTTPS et que j'essayais de frapper via AJAX une API qui était en HTTP. Mais le navigateur ne nous permettra pas de faire cela.

Donc, si vous ne pouvez pas définir l'API sur HTTPS (c'était mon cas), nous pouvons toujours aborder cela d'une manière différente.

Le problème principal n'était pas le problème du contenu mixte, c'était que je voulais soumettre des données à une API et rediriger les utilisateurs vers une page de remerciement sophistiquée. Au lieu d'utiliser AJAX, j'ai créé un fichier php qui reçoit les données, l'envoie en utilisant curl à l'API (car cela se fait côté serveur, il n'y a pas de problème de contenu mixte) et redirige mon utilisateur heureux vers une page de remerciement sophistiquée.

StormRage
la source
Avez-vous une version sécurisée de votre API? Vous devrez demander via HTTPS si vous utilisez un site sécurisé comme origine.
Cameron Tinker
1
Non, je ne le fais pas, y a-t-il un autre moyen de le faire? Je veux dire que la demande est
acceptée
Vous pouvez créer une URL HTTPS dans Apache vers un proxy XX.XXX.XX.XXvia HTTP. Cependant, si le but de HTTP est de protéger les informations de l'utilisateur, vous devrez faire attention à ce que l'itinéraire entre les serveurs ne passe pas par l'Internet public.
halfer

Réponses:

92

Si vous chargez une page dans votre navigateur en utilisant HTTPS, le navigateur refusera de charger des ressources via HTTP. Comme vous l'avez essayé, modifier l'URL de l'API pour qu'elle utilise HTTPS au lieu de HTTP résout généralement ce problème . Cependant, votre API ne doit pas autoriser les connexions HTTPS. Pour cette raison, vous devez forcer HTTP sur la page principale ou leur demander d'autoriser les connexions HTTPS.

Remarque à ce sujet: la requête fonctionnera toujours si vous accédez à l'URL de l'API au lieu d'essayer de la charger avec AJAX. En effet, le navigateur ne charge pas une ressource à partir d'une page sécurisée, mais il charge une page non sécurisée et il l'accepte. Pour qu'il soit disponible via AJAX, cependant, les protocoles doivent correspondre.

Mikel Bitson
la source
1
OK, l'API est sur mon serveur, y a-t-il un guide que je peux suivre pour le rendre https?
StormRage
1
@StormRage Absolument! Quel type de serveur utilisez-vous? Apache? S'agit-il d'un hébergement mutualisé ou d'un serveur privé?
Mikel Bitson
@StormRage Veuillez me faire savoir si vous avez besoin d'aide supplémentaire. Sinon, le vote stimulera l'aide publique que vous obtenez ici sur SO.
Mikel Bitson
1
Désolé d'être en retard sur ce point, j'ai réussi à le résoudre sans utiliser AJAX, mes solutions incluent des fonctions wordpress / php curl, je poste ma solution dès que possible, devrais-je simplement modifier ma question et écrire ma solution, ou Dois-je utiliser le bouton "Répondez à votre propre question"?
StormRage
1
Souligné la partie pertinente de la réponse ici. La seule solution pratique à cela est d'utiliser HTTPS
Liam
131

J'ai résolu ce problème en ajoutant le code suivant à la page HTML, car nous utilisons l'API tierce qui n'est pas contrôlée par nous.

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

J'espère que cela aiderait, et pour mémoire aussi.

Ciel
la source
8
Cela met à niveau toutes les httpdemandes d'utilisation https, vous n'avez donc pas besoin de changer le protocole pour chaque appel.
eithed
3
Cela a fonctionné pour moi, mais malheureusement cela ne fonctionne pas avec Internet Explorer: developer.mozilla.org/en-US/docs/Web/HTTP/Headers/...
Ciaran Gallagher
2
J'ai essayé cela mais maintenant j'obtiens une erreur CORS sur firefox et net :: ERR_SSL_PROTOCOL_ERROR sur chrome. Je sais que tous les appels fonctionnent parce que ma page Web était auparavant http, mais maintenant que j'ai changé en https, ces appels ne fonctionnent pas. y a-t-il autre chose que je peux ajouter à mon fichier html principal? Parce que si je suis les étapes de @Juanma Menendez, tous les appels fonctionnent mais je ne peux pas m'attendre à ce que chaque utilisateur fasse cela.
Otorrinolaringologista -man
Je me débat avec ce problème depuis des heures jusqu'à ce que je trouve votre réponse, merci beaucoup!
Muhab
Nous confirmons que cette solution fonctionne dans notre cas, peut-être que cela vous aidera aussi à l'avenir: nous avons essayé d'établir une fonctionnalité de streaming en direct / vidéo à la demande HTTP segmentée, quelque chose comme www.example.com/blabla/master.m3u8. Tout a bien fonctionné sur http. Mais lorsque nous le migrons vers https, cela ne fonctionnera tout simplement pas. Nous avons découvert que l'initiale master.m3u8était en mesure de faire la httpsdemande, mais le segment de vidéo segmenté suivant était toujours utilisé http(car nous utilisons un module tiers). Peu importe ce que nous modifions, il ne sera tout simplement pas utilisé https. Utilisé cette politique et a fonctionné instantanément comme un charme!
rahmatns
34

Si vous visitez simplement une page Web en laquelle vous avez confiance et que vous souhaitez avancer rapidement, il vous suffit de:

1- Cliquez sur l'icône du bouclier à l'extrême droite de la barre d'adresse.

Autoriser le contenu mixte dans Google Chrome

2- Dans la fenêtre pop-up, cliquez sur «Charger quand même» ou «Charger un script non sécurisé» (selon votre version de Chrome).


Si vous souhaitez configurer votre navigateur Chrome sur TOUJOURS (dans toutes les pages Web) autoriser le contenu mixte:

1- Dans un navigateur Chrome ouvert, appuyez sur Ctrl + Maj + Q sur votre clavier pour forcer la fermeture de Chrome. Chrome doit être complètement fermé avant les étapes suivantes.

2- Cliquez avec le bouton droit sur l'icône du bureau Google Chrome (ou sur le lien du menu Démarrer). Sélectionnez Propriétés.

3- A la fin des informations existantes dans le champ Cible, ajoutez: "--allow-running-insecure-content" (Il y a un espace avant le premier tiret.)

4- Cliquez sur OK.

5- Ouvrez Chrome et essayez de lancer le contenu qui a été bloqué précédemment. Cela devrait fonctionner maintenant.

Juanma Menendez
la source
4
Cela ne fait rien pour les personnes qui conçoivent des sites Web pour les utilisateurs qui ne souhaitent pas modifier leurs paramètres pour que le site fonctionne sur leur navigateur, par exemple, l'OP.
smallpants
12

La raison de cette erreur est très simple. Votre AJAX essaie d'appeler via HTTP alors que votre serveur fonctionne sur HTTPS, donc votre serveur refuse d'appeler votre AJAX. Cela peut être résolu en ajoutant la ligne suivante à l'intérieur de la balise head de votre fichier HTML principal:

<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests"> 
Sobhan Niroula
la source
il le permet mais la demande est https
BG BRUNO
Dans mon cas. le serveur demande uniquement HTTP. J'essaie que <meta> ne fonctionne pas. Le navigateur dit une erreur de demande à l'URL.
iHad 169
1

Si votre code API s'exécute sur un serveur node.js, vous devez y concentrer votre attention, pas dans Apache ou NGINX. Mikel a raison, changer l'URL de l'API en HTTPS est la réponse, mais si votre API appelle un serveur node.js, il vaut mieux la configurer pour HTTPS! Et bien sûr, le serveur node.js peut être sur n'importe quel port inutilisé, il n'est pas nécessaire qu'il s'agisse du port 443.

mcmacerson
la source
L'API était tierce, donc je ne pouvais pas la définir sur https, et comme vous pouvez le voir dans l'url que j'essayais de frapper, l'API était codée en PHP
StormRage
@StormRage Votre question et la réponse de Mikel ont conduit à une solution à mon problème, alors j'ai pensé en prendre note ici même si ma réponse ne s'applique pas vraiment à votre situation.
mcmacerson le
Eh bien, vous et Mikel avez raison, la solution la plus raisonnable serait d'utiliser ssl dans l'API, mais dans ce contexte, je n'ai pas été en mesure de le faire car c'était une API tierce, mais une solution pour les personnes utilisant wordpress ou tout site hérité peut envoyer les données à leur backend et envoyer la demande à l'API au sein du serveur.
StormRage
J'ai implémenté l'api par laravel en tant que côté serveur et application ionique en tant que PWA sur le même hôte, donc j'ai la même erreur mentionnée dans cet article stackoverflow.com/q/56157129/308578
sabre tabatabaee yazdi
1

Au lieu d'utiliser la méthode Ajax Post, vous pouvez utiliser la forme dynamique avec l'élément. Cela fonctionnera même si la page est chargée en SSL et que la source soumise n'est pas SSL.

Vous devez définir la valeur de l'élément du formulaire.

En fait, un nouveau formulaire dynamique s'ouvrira en mode non SSL dans un onglet séparé du navigateur lorsque l'attribut cible a défini '_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()
Proneet Ray
la source
Je veux en fait accéder à une API, mais lorsque je le fais avec votre méthode en faisant une demande d'obtention, je soumettrais en fait un formulaire, mais maintenant je suis obligé de lire la réponse de l'API. Parce que je suppose que AJAX ou xmlhttprequest est la seule option
Siddharth Choudhary
solution intéressante :-)
BG BRUNO
simple et brillant
Harkal
0

J'avais le même problème, mais pour moi, le problème était la commande ng build. Je faisais "ng build --prod" je l'ai corrigé en "ng build --prod --base-href / applicationname /". et cela a résolu mon problème.

Narender Gandi
la source
0

dans mon cas, mon hôte local était httpet ma version déployée l'était https, j'ai donc utilisé ce script pour ajouter la balise meta http-equiv uniquement pour 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)
}
yaya
la source