“Conteúdo misto bloqueado” ao executar uma operação HTTP AJAX em uma página HTTPS

108

Tenho um formulário que estou enviando (por meio de GET, pois é necessário dessa forma) para um crm (ViciDial). Posso enviar o formulário com êxito, no entanto, se fizer isso, o arquivo de processamento em crm apenas exibirá um texto de sucesso e pronto.

Em vez desse texto, desejo exibir uma página de agradecimento em meu site, então decidi usar AJAX para enviar o formulário e redirecioná-lo para a página de que preciso, mas estou recebendo este erro no meu navegador:

Conteúdo misto: a página em ' https://page.com ' foi carregada por HTTPS, mas solicitou um ponto de extremidade XMLHttpRequest inseguro ' http://XX.XXX.XX.XXX/vicidial/non_agent_api.php?queries=query=data '. Esta solicitação foi bloqueada; o conteúdo deve ser servido por HTTPS.

Este é meu 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>

Apenas definir https na URL não funcionará. Existe alguma maneira de enviar os dados via GET e redirecionar o usuário para a minha página de agradecimento?

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

O problema aqui era conteúdo misto, isso significa que carreguei uma página via HTTPS e estava tentando acertar via AJAX uma API que estava em HTTP. Mas o navegador não nos permite apenas fazer isso.

Portanto, se você não pode definir a API como HTTPS (este foi o meu caso), ainda podemos abordar isso de uma maneira diferente.

O principal problema não era o problema de conteúdo misto, era que eu queria enviar dados para uma API e redirecionar os usuários para uma página de agradecimento sofisticada. Em vez de usar AJAX, criei um arquivo php que recebe os dados e os envia usando curl para a API (como isso está sendo feito no lado do servidor, não há problema de conteúdo misto) e redireciona meu feliz usuário para uma página de agradecimento sofisticada.

StormRage
fonte
Você tem uma versão segura de sua API? Você precisará solicitar HTTPS se estiver usando um site seguro como origem.
Cameron Tinker
1
Não, não tenho, há alguma outra maneira pela qual eu poderia fazer isso? Quero dizer, a solicitação passa se apenas usar o formulário de envio sem Ajax
StormRage
Você pode criar uma URL HTTPS no Apache para proxy para XX.XXX.XX.XXsobre HTTP. No entanto, se o objetivo do HTTP é proteger as informações do usuário, você precisará ter cuidado para que a rota entre os servidores não passe pela Internet pública.
dia

Respostas:

89

Se você carregar uma página em seu navegador usando HTTPS, o navegador se recusará a carregar quaisquer recursos por HTTP. Como você tentou, alterar o URL da API para HTTPS em vez de HTTP normalmente resolve esse problema . No entanto, sua API não deve permitir conexões HTTPS. Por isso, você deve forçar o HTTP na página principal ou solicitar que eles permitam conexões HTTPS.

Observação sobre isso: a solicitação ainda funcionará se você acessar a URL da API em vez de tentar carregá-la com AJAX. Isso ocorre porque o navegador não está carregando um recurso de uma página segura, em vez disso, está carregando uma página não segura e está aceitando isso. Para que esteja disponível por meio do AJAX, no entanto, os protocolos devem ser correspondentes.

Mikel Bitson
fonte
1
OK, a api está no meu servidor, há algum guia que eu possa seguir para torná-la https?
StormRage
1
@StormRage Absolutamente! Que tipo de servidor você está executando? Apache? É uma hospedagem compartilhada ou um servidor privado?
Mikel Bitson
@StormRage Informe-nos se precisar de mais ajuda. Caso contrário, a votação incentivará a assistência pública que você obtém aqui no SO.
Mikel Bitson
1
Desculpe pelo atraso, consegui resolver sem usar AJAX, minhas soluções incluem algumas funções wordpress / php curl, postarei minha solução assim que puder, devo apenas editar minha pergunta e escrever minha solução nela, ou devo usar o botão que diz "responda à sua própria pergunta"?
StormRage
1
Destaque a parte relevante da resposta aqui. A única solução prática para isso é usar HTTPS
Liam
129

Resolvi isso adicionando o seguinte código à página HTML, uma vez que estamos usando a API de terceiros que não é controlada por nós.

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

Espero que isso ajude, e para registro também.

Céu
fonte
8
Isso atualiza todas as httpsolicitações a serem usadas https, para que você não precise alterar o protocolo de cada chamada.
8 de
3
Isso funcionou para mim, mas infelizmente não funciona com o Internet Explorer: developer.mozilla.org/en-US/docs/Web/HTTP/Headers/…
Ciaran Gallagher
2
Eu tentei isso, mas agora estou recebendo erro CORS no firefox e net :: ERR_SSL_PROTOCOL_ERROR no Chrome. Sei que todas as chamadas funcionam porque minha página da Web era http antes, mas agora que mudei para https, essas chamadas não estão funcionando. há algo mais que eu possa adicionar ao meu arquivo html principal? Porque se eu seguir os passos de @Juanma Menendez, todas as chamadas funcionam, mas não posso esperar que todos os usuários façam isso.
Otorrinolaringologista -man
Tenho lutado com esse problema por horas até que encontrei sua resposta, muito obrigado!
Muhab
Confirmamos que esta solução funciona em nosso caso, apenas talvez ajude você também no futuro: tentamos estabelecer um recurso de streaming / vídeo sob demanda HTTP segmentado, algo como www.example.com/blabla/master.m3u8. Tudo funcionou bem no http. Mas quando estamos migrando para https, ele simplesmente não funciona. Descobrimos que o inicial master.m3u8era capaz de fazer a httpssolicitação, mas o seguinte trecho de vídeo segmentado estava sempre usando http(porque estamos usando um módulo de terceiros). Não importa o que ajustemos, ele simplesmente não usará https. Usei essa política e funcionou instantaneamente como um encanto!
rahmatns
34

Se você estiver apenas visitando uma página da web em que confia e quiser avançar rapidamente, basta:

1- Clique no ícone de escudo na extremidade direita da barra de endereço.

Permitir conteúdo misto no Google Chrome

2- Na janela pop-up, clique em "Carregar mesmo assim" ou "Carregar script não seguro" (dependendo da versão do Chrome).


Se você deseja configurar seu navegador Chrome para SEMPRE (em todas as páginas da web) permitir conteúdo misto:

1- Em um navegador Chrome aberto, pressione Ctrl + Shift + Q no teclado para forçar o fechamento do Chrome. O Chrome deve ser totalmente fechado antes das próximas etapas.

2- Clique com o botão direito no ícone da área de trabalho do Google Chrome (ou no link do Menu Iniciar). Selecione Propriedades.

3- Ao final das informações existentes no campo Destino, adicione: "--allow-running-insecure-content" (há um espaço antes do primeiro travessão).

4- Clique em OK.

5- Abra o Chrome e tente iniciar o conteúdo que foi bloqueado anteriormente. Deve funcionar agora.

Juanma Menendez
fonte
4
Isso não faz nada para as pessoas que projetam sites para aqueles usuários que não desejam alterar suas configurações para fazer o site funcionar em seu navegador, por exemplo, o OP.
calças pequenas
12

O motivo desse erro é muito simples. Seu AJAX está tentando chamar por HTTP enquanto seu servidor está executando por HTTPS, então seu servidor está negando a chamada de seu AJAX. Isso pode ser corrigido adicionando a seguinte linha dentro da tag head do seu arquivo HTML principal:

<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests"> 
Sobhan Niroula
fonte
permite, mas a solicitação é https
BG BRUNO
No meu caso. o servidor apenas solicitação de HTTP. Eu tento que <meta> não funciona. O navegador diz erro de solicitação no URL.
iHad 169 de
1

Se o código da API estiver sendo executado em um servidor node.js , você precisa focar sua atenção nele, não no Apache ou NGINX. Mikel está certo, mudar a URL da API para HTTPS é a resposta, mas se sua API está chamando um servidor node.js, é melhor configurá-la para HTTPS! E, claro, o servidor node.js pode estar em qualquer porta não utilizada, não precisa ser a porta 443.

Mcmacerson
fonte
A API era de terceiros, então não havia como configurá-la para https e, como você pode ver no url que estava tentando
acessar
@StormRage Sua pergunta e a resposta de Mikel levaram a uma solução para meu problema, então pensei em anotar isso aqui, embora minha resposta não se aplique realmente à sua situação.
Mcmacerson
Bem, você e Mikel estão certos, a solução mais razoável seria fazer uso de ssl na API, mas neste contexto eu não fui capaz de fazer isso porque era uma API de terceiros, mas uma solução para ppl usando wordpress ou qualquer site legado pode estar enviando os dados para seu back-end e enviar a solicitação à API no servidor.
StormRage
Eu implementei api por laravel como servidor e aplicativo iônico como PWA no mesmo host, então eu tenho o mesmo erro mencionado neste artigo stackoverflow.com/q/56157129/308578
sabre tabatabaee yazdi
1

Em vez de usar o método Ajax Post, você pode usar a forma dinâmica junto com o elemento. Funcionará mesmo que a página seja carregada em SSL e a fonte enviada não seja SSL.

Você precisa definir o valor do valor do elemento do formulário.

Na verdade, um novo formulário dinâmico será aberto como modo não SSL em uma guia separada do navegador quando o atributo de destino tiver definido '_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()
Raio Proneet
fonte
Na verdade, quero atingir uma API, mas quando faço isso com o seu método, fazendo uma solicitação get, na verdade estaria enviando um formulário, mas agora estou preso na leitura da resposta da API. Porque eu acho que para esse AJAX ou xmlhttprequest é a única opção
Siddharth Choudhary
solução interessante :-)
BG BRUNO
simples e brilhante
Harkal
0

Eu estava com o mesmo problema, mas para mim o problema era o comando build. Eu estava fazendo "ng build --prod" e corrigi-lo para "ng build --prod --base-href / applicationname /". e isso resolveu meu problema.

Narender Gandi
fonte
0

no meu caso, meu localhost era httpe minha versão implantada era https, então usei este script para adicionar a metatag http-equiv apenas 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
fonte