«Смешанное содержимое заблокировано» при выполнении операции HTTP AJAX на странице HTTPS.

111

У меня есть форма, которую я отправляю (через GET, как это требуется) в crm (ViciDial). Я могу успешно отправить форму, однако, если я это сделаю, файл обработки в crm просто отобразит текст успеха, и все.

Вместо этого текста я хочу отобразить страницу с благодарностью на своем веб-сайте, поэтому я решил использовать AJAX для отправки формы и перенаправления ее на нужную мне страницу, однако в моем браузере появляется эта ошибка:

Смешанный контент: страница https://page.com была загружена по HTTPS, но запросила небезопасную конечную точку XMLHttpRequest http://XX.XXX.XX.XXX/vicidial/non_agent_api.php?queries=query=data '. Этот запрос был заблокирован; контент должен обслуживаться по HTTPS.

Это мой сценарий 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>

Простая установка https в URL-адресе не сработает, есть ли способ отправить данные через GET и перенаправить пользователя на мою страницу благодарности?

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

Проблема здесь была в смешанном содержимом, это означает, что я загрузил страницу через HTTPS и пытался через AJAX использовать API, который был в HTTP. Но браузер не позволяет нам просто делать это.

Поэтому, если вы не можете настроить API на HTTPS (это был мой случай), мы все равно можем подойти к этому по-другому.

Основная проблема заключалась не в смешанном содержании, а в том, что я хотел отправить данные в API и перенаправить пользователей на красивую страницу с благодарностью. Вместо использования AJAX я создал файл php, который получает данные, отправляет их с помощью curl в API (поскольку это делается на стороне сервера, нет проблем со смешанным содержимым) и перенаправляет моего счастливого пользователя на красивую страницу с благодарностью.

Буря ярости
источник
У вас есть безопасная версия вашего API? Вам нужно будет запросить через HTTPS, если вы используете безопасный сайт в качестве источника.
Кэмерон Тинкер
1
Нет, не знаю, есть ли другой способ сделать это? Я имею в виду, что запрос проходит, если просто использовать форму submit без Ajax
StormRage
Вы можете создать URL-адрес HTTPS в Apache для прокси-сервера XX.XXX.XX.XXчерез HTTP. Однако, если целью HTTP является защита информации пользователя, вам нужно быть осторожным, чтобы маршрут между серверами не проходил через общедоступный Интернет.
Halfer

Ответы:

93

Если вы загрузите страницу в своем браузере с использованием HTTPS, браузер откажется загружать любые ресурсы по HTTP. Как вы уже пытались, изменение URL-адреса API на HTTPS вместо HTTP обычно решает эту проблему . Однако ваш API не должен разрешать HTTPS-соединения. Из-за этого вы должны либо принудительно использовать HTTP на главной странице, либо запросить разрешение HTTPS-соединений.

Примечание по этому поводу: запрос по-прежнему будет работать, если вы перейдете по URL-адресу API, а не попытаетесь загрузить его с помощью AJAX. Это связано с тем, что браузер не загружает ресурс из защищенной страницы, а загружает небезопасную страницу и принимает это. Однако для того, чтобы он был доступен через AJAX, протоколы должны совпадать.

Микель Битсон
источник
1
Хорошо, api находится на моем сервере, есть ли какое-нибудь руководство, которому я могу следовать, чтобы сделать его https?
StormRage
1
@StormRage Совершенно верно! Какой тип сервера вы используете? Апач? Это виртуальный хостинг или частный сервер?
Mikel Bitson
@StormRage Пожалуйста, дайте мне знать, если вам понадобится дополнительная помощь. В противном случае голосование будет стимулировать общественную помощь, которую вы получаете здесь, на SO.
Mikel Bitson
1
Извините за опоздание, мне удалось решить эту проблему без использования AJAX, мои решения включают в себя некоторые функции wordpress / php curl, я опубликую свое решение, как только смогу, должен ли я просто отредактировать свой вопрос и написать свое решение в нем, или я должен использовать кнопку с надписью «ответь на свой вопрос»?
StormRage
1
Выделил здесь соответствующую часть ответа. Единственное практическое решение - использовать HTTPS,
Лиам
132

Я решил это, добавив следующий код на HTML-страницу, поскольку мы используем сторонний API, который не контролируется нами.

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

Надеюсь, это поможет, и для записи тоже.

Небо
источник
8
Это обновляет все httpзапросы для использования https, поэтому вам не нужно менять протокол для каждого вызова.
написано
3
Это сработало для меня, но, к сожалению, это не работает с Internet Explorer: developer.mozilla.org/en-US/docs/Web/HTTP/Headers/…
Киаран Галлахер
2
Я пробовал это, но теперь у меня появляется ошибка CORS на firefox и net :: ERR_SSL_PROTOCOL_ERROR на chrome. Я знаю, что все вызовы работают, потому что моя веб-страница раньше была http, но теперь, когда я перешел на https, эти вызовы не работают. Есть ли что-нибудь еще, что я могу добавить в свой основной файл HTML? Потому что, если я буду следовать шагам @Juanma Menendez, все вызовы будут работать, но я не могу ожидать, что каждый пользователь сделает это.
Оторриноларингологист-мужчина
Я часами боролся с этой проблемой, пока не нашел ваш ответ, большое спасибо!
Мухаб
Мы подтверждаем, что это решение работает в нашем случае, но, возможно, поможет и вам в будущем: мы попытались создать сегментированную функцию потоковой передачи HTTP / видео по запросу, что-то вроде www.example.com/blabla/master.m3u8. Все отлично работало на http. Но когда мы переводим его на https, это просто не сработает. Мы выяснили, что исходный запрос master.m3u8мог выполнить https, но следующий сегментированный фрагмент видео всегда использовался http(потому что мы используем сторонний модуль). Независимо от того, что мы настраиваем, он просто не будет использоваться https. Воспользовался этой политикой и сразу сработал как шарм!
rahmatns
34

Если вы просто посещаете веб-страницу, которой доверяете, и хотите быстро двигаться вперед, просто:

1- Щелкните значок щита в правом углу адресной строки.

Разрешить смешанный контент в Google Chrome

2- Во всплывающем окне нажмите «Все равно загрузить» или «Загрузить небезопасный скрипт» (в зависимости от версии Chrome).


Если вы хотите настроить браузер Chrome на ВСЕГДА (на всех веб-страницах), разрешать смешанный контент:

1. В открытом браузере Chrome нажмите Ctrl + Shift + Q на клавиатуре, чтобы принудительно закрыть Chrome. Перед выполнением следующих действий необходимо полностью закрыть Chrome.

2- Щелкните правой кнопкой мыши значок Google Chrome на рабочем столе (или ссылку в меню «Пуск»). Выберите Свойства.

3- В конце существующей информации в поле «Цель» добавьте: «--allow-running-insecure-content» (перед первым тире есть пробел).

4- Щелкните ОК.

5- Откройте Chrome и попробуйте запустить ранее заблокированный контент. Теперь он должен работать.

Хуанма Менендес
источник
4
Это ничего не делает для людей, разрабатывающих веб-сайты для тех пользователей, которые не хотят изменять свои настройки, чтобы сайт работал в их браузере, например OP.
smallpants 06
13

Причина этой ошибки очень проста. Ваш AJAX пытается вызвать через HTTP, тогда как ваш сервер работает через HTTPS, поэтому ваш сервер запрещает вызов вашего AJAX. Это можно исправить, добавив следующую строку в тег заголовка вашего основного HTML-файла:

<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests"> 
Собхан Нирула
источник
это позволяет, но запрос https
BG BRUNO
В моем случае. сервер только HTTP-запрос. Я пытаюсь, чтобы этот <meta> не работал. Браузер сообщает об ошибке запроса по URL-адресу.
iHad 169,
1

Если ваш код API работает на сервере node.js, вам нужно сосредоточить свое внимание на нем, а не на Apache или NGINX. Микель прав, изменение URL-адреса API на HTTPS - это ответ, но если ваш API вызывает сервер node.js, его лучше настроить для HTTPS! И, конечно же, сервер node.js может быть на любом неиспользуемом порту, это не обязательно должен быть порт 443.

McMacerson
источник
API был сторонним, поэтому у меня не было возможности установить его на https, и, как вы можете видеть по URL-адресу, который я пытался использовать, API был
написан
@StormRage Ваш вопрос и ответ Микеля привели к решению моей проблемы, поэтому я подумал, что отмечу это здесь, хотя мой ответ на самом деле не относится к вашей ситуации.
mcmacerson 04
Что ж, вы и Микель правы, наиболее разумным решением было бы использовать ssl в API, но в данном контексте я не смог этого сделать, поскольку это был сторонний API, а решение для ppl с использованием wordpress или любой унаследованный сайт может отправлять данные на свой бэкэнд и отправлять запрос API на сервере.
StormRage 05
Я реализовал api от laravel как серверную часть и ионное приложение как PWA на том же хосте, поэтому у меня такая же ошибка, упомянутая в этой статье stackoverflow.com/q/56157129/308578
saber tabatabaee yazdi
1

Вместо использования метода Ajax Post вы можете использовать динамическую форму вместе с element. Он будет работать, даже если страница загружена с использованием SSL, а отправленный источник не является SSL.

Вам необходимо установить значение value элемента формы.

Фактически новая динамическая форма откроется как режим без SSL на отдельной вкладке браузера, если целевой атрибут установлен '_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
источник
Я действительно хочу использовать API, но когда я делаю это с вашим методом, делая запрос на получение, я бы фактически отправлял форму, но теперь я застрял в чтении ответа от API. Потому что, я думаю, для этого AJAX или xmlhttprequest - единственный вариант
Сиддхарт Чоудхари
интересное решение :-)
BG BRUNO
просто и гениально
Harkal
0

У меня была такая же проблема, но для меня проблема заключалась в команде ng build. Я делал "ng build --prod", я исправил его на "ng build --prod --base-href / applicationname /". и это решило мою проблему.

Нарендер Ганди
источник
0

в моем случае это был мой локальный хост httpи моя развернутая версия https, поэтому я использовал этот скрипт, чтобы добавить метатег http-Equiv только для 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
источник