"Змішаний вміст заблокований" під час запуску операції HTTP AJAX на сторінці HTTPS


110

У мене є форма, яку я надсилаю (через 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, якщо ви використовуєте захищений сайт як джерело.
Cameron Tinker

1
Ні, я ні, чи є інший спосіб, яким я міг би це зробити? Я маю на увазі, що запит проходить, якщо просто скористатись формою для надсилання без Ajax
StormRage

Ви можете створити URL-адресу HTTPS в Apache для проксі для XX.XXX.XX.XXHTTP. Однак якщо метою HTTP є захист інформації користувача, вам потрібно бути обережним, щоб маршрут між серверами не проходив через загальнодоступний Інтернет.
половина

Відповіді:


90

Якщо ви завантажите сторінку у своєму браузері за допомогою HTTPS, браузер відмовиться завантажувати будь-які ресурси через HTTP. Як ви вже намагалися, зміна URL-адреси API на HTTPS замість HTTP зазвичай вирішує цю проблему . Однак ваш API не повинен дозволяти з'єднання HTTPS. Через це потрібно або змусити HTTP на головній сторінці або попросити, щоб вони дозволяли HTTPS-з'єднання.

Зверніть увагу на це: Запит все одно буде працювати, якщо ви перейдете до URL-адреси API замість того, щоб намагатися завантажити його AJAX. Це тому, що браузер не завантажує ресурс із захищеної сторінки, натомість завантажує незахищену сторінку, і це приймає. Для того, щоб він був доступний через AJAX, протоколи повинні збігатися.


1
Гаразд, api є на моєму сервері, чи є якийсь посібник, який я можу дотримуватися, щоб зробити його https?
StormRage

1
@StormRage Абсолютно! Який тип сервера ви працюєте? Апач? Це спільний хостинг або приватний сервер?
Мікель Бітсон

@StormRage Будь ласка, повідомте мене, якщо вам потрібна додаткова допомога. В іншому випадку голосування стимулюватиме публічну допомогу, яку ви отримуєте тут на SO.
Мікель Бітсон

1
Вибачте за те, що запізнилися на це, мені вдалося вирішити це, не використовуючи AJAX, мої рішення включають деякі функції wordpress / php curl, я неправильно розміщую своє рішення, як тільки я можу, чи повинен я просто відредагувати своє запитання і написати в ньому своє рішення, або я повинен використовувати кнопку, на якій написано "відповісти на власне запитання"?
StormRage

1
Тут висвітлено відповідну частину відповіді. Єдиним практичним рішенням для цього є використання HTTPS
Ліам

131

Я вирішив це, додавши наступний код на сторінку 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/…
Ciaran Gallagher

2
Я спробував це, але тепер я отримую помилку CORS на firefox та net :: ERR_SSL_PROTOCOL_ERROR на хромі. Я знаю, що всі дзвінки працюють, тому що моя веб-сторінка раніше була http, але тепер, коли я змінився на https, ці дзвінки не працюють. є ще що-небудь, що я можу додати до мого головного html-файлу? Тому що якщо я слідую за кроками @Juanma Menendez, усі дзвінки працюють, але я не можу очікувати, що кожен користувач це зробить.
Otorrinolaringologista -ман

Я боровся з цим питанням годинами, поки я не знайшов вашу відповідь, дякую багато!
Мухаб

Ми підтверджуємо, що це рішення працює в нашому випадку, можливо, можливо, допоможе і вам у майбутньому. Ми намагалися створити сегментовану функцію потокового / відео трансляції 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- В кінці наявної інформації в полі "Ціль" додайте: "--пустіть незапущений контент" (Перед першим тире є пробіл.)

4- Клацніть OK.

5- Відкрийте Chrome і спробуйте запустити вміст, який був заблокований раніше. Це має працювати зараз.


4
Це не робить нічого для людей, які розробляють веб-сайти для тих користувачів, які не хочуть змінювати свої налаштування, щоб змусити сайт працювати у своєму браузері, наприклад, ОП.
маленькі штани

12

Причина цієї помилки дуже проста. Ваш AJAX намагається зателефонувати через HTTP, тоді як ваш сервер працює над HTTPS, тому ваш сервер відмовляється викликати ваш AJAX. Це можна виправити, додавши наступний рядок всередині тегу головного HTML-файлу:

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

це дозволяє, але запит https
BG BRUNO

У моєму випадку. сервер лише HTTP-запит. Я намагаюся, що це <мета> не може працювати. Помилка запиту веб-переглядача за URL-адресою.
iHad 169

1

Якщо ваш код API працює на сервері node.js, тоді вам потрібно зосередити свою увагу там, а не на Apache або NGINX. Мікель має рацію, зміна URL-адреси API на HTTPS - це відповідь, але якщо ваш API викликає сервер node.js, краще налаштуйте його на HTTPS! І звичайно, сервер node.js може бути на будь-якому невикористаному порту, це не обов'язково повинен бути порт 443.


API був третьою стороною, тому я не мав можливості встановити його на https, і як ви бачите в URL-
адресі, яку

@StormRage Ваше запитання та відповідь Мікель призвели до вирішення моєї проблеми, тому я подумав, що тут це зауважте, навіть якщо моя відповідь не стосується вашої ситуації.
mcmacerson

Що ж, ви та Мікель маєте рацію, найбільш розумним рішенням буде використання ssl в API, але в цьому контексті я не зміг цього зробити, оскільки це був сторонній API, але рішення для ppl за допомогою wordpress або будь-який застарілий сайт може надсилати дані до їхнього сервера та надсилати запит до API на сервері.
StormRage

я реалізований апі по Laravel в стороні сервера і іонного застосування в якості PWA на одному хості , так я ж помилка згадується в цій статті stackoverflow.com/q/56157129/308578
шабля tabatabaee Yazdi

1

Замість використання методу Ajax Post ви можете використовувати динамічну форму разом з елементом. Він буде працювати, навіть сторінка завантажується в SSL, а подане джерело не є SSL.

Вам потрібно встановити значення значення елемента форми.

Насправді нова динамічна форма відкриється як режим, що не є SSL, на окремій вкладці браузера, коли для атрибута target буде встановлено "_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()

Я насправді хочу звернутися до API, але коли я це роблю з вашим методом, роблячи запит на отримання, я фактично надсилаю форму, але тепер я затримався з читанням відповіді з API. Тому що я здогадуюсь, що єдиний варіант
Siddharth

рішення за
BG BRUNO

простий і блискучий
Харкал

0

Я була такою ж проблемою, але для мене проблема полягала в складанні команди. Я робив "ng build --prod", я виправив його на "ng build --prod --base-href / applicationname /". і це вирішило мою проблему.


0

у моєму випадку мій localhost був, 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)
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.