"Contenido mixto bloqueado" cuando se ejecuta una operación HTTP AJAX en una página HTTPS

109

Tengo un formulario que estoy enviando (a través de GET, ya que se requiere de esta manera) a un crm (ViciDial). Puedo enviar el formulario con éxito, sin embargo, si lo hago, el archivo de procesamiento en crm solo hará eco de un texto de éxito y eso es todo.

En lugar de ese texto, quiero mostrar una página de agradecimiento en mi sitio web, así que decidí usar AJAX para enviar el formulario y redirigirlo a la página que necesito, sin embargo, recibo este error en mi navegador:

Contenido mixto: la página en ' https://page.com ' se cargó a través de HTTPS, pero solicitó un punto final XMLHttpRequest no seguro ' http://XX.XXX.XX.XXX/vicidial/non_agent_api.php?queries=query=data '. Esta solicitud ha sido bloqueada; el contenido debe publicarse a través de HTTPS.

Este es mi 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>

El simple hecho de configurar https en la URL no funcionará, ¿hay alguna forma en la que pueda enviar los datos a través de GET y redirigir al usuario a mi página de agradecimiento?

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

El problema aquí fue contenido mixto, esto significa que cargué una página a través de HTTPS y estaba tratando de acceder a través de AJAX a una API que estaba en HTTP. Pero el navegador no nos permitirá hacer eso.

Entonces, si no puede configurar la API para que sea HTTPS (este fue mi caso), aún podemos abordar esto de una manera diferente.

El problema principal no era el problema del contenido mixto, era que quería enviar datos a una API y redirigir a los usuarios a una elegante página de agradecimiento. En lugar de usar AJAX, hice un archivo php que recibe los datos y los envía usando curl a la API (ya que esto se está haciendo en el lado del servidor, no hay problemas de contenido mixto) y redirige a mi usuario feliz a una elegante página de agradecimiento.

Furia de tormenta
fuente
¿Tiene una versión segura de su API? Deberá solicitar a través de HTTPS si está utilizando un sitio seguro como origen.
Cameron Tinker
1
No, no lo hago, ¿hay alguna otra forma en que pueda hacer eso? Quiero decir que la solicitud se
procesa
Puede crear una URL HTTPS en Apache para proxy a XX.XXX.XX.XXtravés de HTTP. Sin embargo, si el propósito de HTTP es proteger la información del usuario, deberá tener cuidado de que la ruta entre los servidores no pase por la Internet pública.
halfer

Respuestas:

90

Si carga una página en su navegador usando HTTPS, el navegador se negará a cargar recursos a través de HTTP. Como lo ha intentado, cambiar la URL de la API para que tenga HTTPS en lugar de HTTP normalmente resuelve este problema . Sin embargo, su API no debe permitir conexiones HTTPS. Debido a esto, debe forzar HTTP en la página principal o solicitar que permitan conexiones HTTPS.

Tenga en cuenta esto: la solicitud seguirá funcionando si accede a la URL de la API en lugar de intentar cargarla con AJAX. Esto se debe a que el navegador no carga un recurso desde una página segura, sino que carga una página insegura y lo acepta. Sin embargo, para que esté disponible a través de AJAX, los protocolos deben coincidir.

Mikel Bitson
fuente
1
Bien, la API está en mi servidor, ¿hay alguna guía que pueda seguir para convertirla en https?
StormRage
1
@StormRage ¡Absolutamente! ¿Qué tipo de servidor está ejecutando? ¿Apache? ¿Es un hosting compartido o un servidor privado?
Mikel Bitson
@StormRage Por favor, avíseme si necesita más ayuda. De lo contrario, votar incentivará la asistencia pública que recibe aquí en SO.
Mikel Bitson
1
Perdón por llegar tarde en esto, logré resolverlo sin usar AJAX, mis soluciones incluyen algunas funciones de wordpress / php curl, publicaré mi solución tan pronto como pueda, debería editar mi pregunta y escribir mi solución en ella, o ¿Debería usar el botón que dice "responde tu propia pregunta"?
StormRage
1
Resalta la parte relevante de la respuesta aquí. La única solución práctica para esto es usar HTTPS
Liam
130

Resolví esto agregando el siguiente código a la página HTML, ya que estamos usando la API de terceros que no está controlada por nosotros.

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

Espero que esto ayude, y también para un récord.

Cielo
fuente
8
Esto actualiza todas las httpsolicitudes de uso https, por lo que no es necesario cambiar el protocolo para cada llamada.
publicado el
3
Esto funcionó para mí, pero desafortunadamente esto no funciona con Internet Explorer: developer.mozilla.org/en-US/docs/Web/HTTP/Headers/…
Ciaran Gallagher
2
Intenté esto, pero ahora recibo el error CORS en Firefox y net :: ERR_SSL_PROTOCOL_ERROR en Chrome. Sé que todas las llamadas funcionan porque mi página web era http antes, pero ahora que cambié a https, estas llamadas no funcionan. ¿Hay algo más que pueda agregar a mi archivo html principal? Porque si sigo los pasos de @Juanma Menendez, todas las llamadas funcionan, pero no puedo esperar que todos los usuarios hagan esto.
Otorrinolaringologista -man el
He estado luchando con este problema durante horas hasta que encontré su respuesta, ¡muchas gracias!
Muhab
Confirmamos que esta solución funciona en nuestro caso, solo que tal vez también lo ayude en el futuro: intentamos establecer una función de transmisión en vivo / video bajo demanda HTTP segmentada, algo así como www.example.com/blabla/master.m3u8. Todo funcionó bien en http. Pero cuando lo estamos migrando a https, simplemente no funcionará. Descubrimos que la inicial master.m3u8podía hacer una httpssolicitud, pero el siguiente fragmento de video segmentado siempre estaba usando http(porque estamos usando un módulo de terceros). No importa lo que modifiquemos, simplemente no se usará https. ¡Usé esta política y funcionó instantáneamente como un encanto!
rahmatns
34

Si está visitando una página web en la que confía y desea avanzar rápidamente, simplemente:

1- Haga clic en el icono del escudo en el extremo derecho de la barra de direcciones.

Permitir contenido mixto en Google Chrome

2- En la ventana emergente, haga clic en "Cargar de todos modos" o "Cargar script inseguro" (dependiendo de su versión de Chrome).


Si desea configurar su navegador Chrome para SIEMPRE (en todas las páginas web) permitir contenido mixto:

1- En un navegador Chrome abierto, presione Ctrl + Shift + Q en su teclado para forzar el cierre de Chrome. Chrome debe estar completamente cerrado antes de los siguientes pasos.

2- Haga clic con el botón derecho en el icono del escritorio de Google Chrome (o en el enlace del menú Inicio). Seleccione Propiedades.

3- Al final de la información existente en el campo Destino, agregue: "--allow-running-insecure-content" (Hay un espacio antes del primer guión).

4- Haga clic en Aceptar.

5- Abra Chrome e intente iniciar el contenido que se bloqueó anteriormente. Debería funcionar ahora.

Juanma Menéndez
fuente
4
Esto no hace nada para las personas que diseñan sitios web para aquellos usuarios que no quieren cambiar su configuración para que el sitio funcione en su navegador, por ejemplo, el OP.
smallpants
12

El motivo de este error es muy sencillo. Su AJAX está tratando de llamar a través de HTTP mientras que su servidor se está ejecutando en HTTPS, por lo que su servidor niega llamar a su AJAX. Esto se puede solucionar agregando la siguiente línea dentro de la etiqueta principal de su archivo HTML principal:

<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests"> 
Sobhan Niroula
fuente
lo permite pero la solicitud es https
BG BRUNO
En mi caso. el servidor solo solicitud HTTP. Intento que <meta> no funcione. El navegador dice error de solicitud en URL.
iHad 169
1

Si su código API se está ejecutando en un servidor node.js, entonces debe enfocar su atención allí, no en Apache o NGINX. Mikel tiene razón, cambiar la URL de la API a HTTPS es la respuesta, pero si su API está llamando a un servidor node.js, ¡es mejor que esté configurado para HTTPS! Y, por supuesto, el servidor node.js puede estar en cualquier puerto no utilizado, no tiene que ser el puerto 443.

Mcmacerson
fuente
La API era de un tercero, por lo que no había forma de que pudiera configurarla en https, y como puede ver en la URL que estaba tratando de
acceder
@StormRage Tu pregunta y la respuesta de Mikel llevaron a una solución para mi problema, así que pensé en tomar nota de ello aquí, aunque mi respuesta no se aplica realmente a tu situación.
mcmacerson
Bueno, tú y Mikel tienen razón, la solución más razonable sería hacer uso de ssl en la API, pero en este contexto no pude hacer eso ya que era una API de terceros, sino una solución para ppl usando wordpress o cualquier sitio heredado podría enviar los datos a su backend y enviar la solicitud a la API dentro del servidor.
StormRage
Implementé api por laravel como lado del servidor y aplicación iónica como PWA en el mismo host, por lo que tengo el mismo error mencionado en este artículo stackoverflow.com/q/56157129/308578
saber tabatabaee yazdi
1

En lugar de usar el método Ajax Post, puede usar la forma dinámica junto con el elemento. Funcionará incluso si la página está cargada en SSL y la fuente enviada no es SSL.

Debe establecer el valor del elemento de la forma.

En realidad, el nuevo formulario dinámico se abrirá como modo no SSL en una pestaña separada del navegador cuando el atributo de destino haya establecido '_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
fuente
De hecho, quiero acceder a una API, pero cuando lo hago con su método al realizar una solicitud de obtención, en realidad estaría enviando un formulario, pero ahora estoy atascado leyendo la respuesta de la API. Porque supongo que AJAX o xmlhttprequest es la única opción
Siddharth Choudhary
solución interesante :-)
BG BRUNO
simple y brillante
Harkal
0

Yo tenía el mismo problema, pero para mí el problema era ng build command. Estaba haciendo "ng build --prod", lo he corregido a "ng build --prod --base-href / applicationname /". y esto resolvió mi problema.

Narender Gandi
fuente
0

en mi caso, mi localhost era httpy mi versión implementada era https, así que usé este script para agregar la metaetiqueta http-equiv solo para 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
fuente