“Nội dung hỗn hợp bị chặn” khi chạy hoạt động HTTP AJAX trong trang HTTPS


108

Tôi đang gửi một biểu mẫu (thông qua GET vì nó được yêu cầu theo cách này) cho một crm (ViciDial). Tôi có thể gửi biểu mẫu thành công tuy nhiên nếu tôi làm như vậy thì tệp xử lý tại crm sẽ chỉ lặp lại một văn bản thành công và thế là xong.

Thay vì văn bản đó, tôi muốn hiển thị trang cảm ơn trên trang web của mình, vì vậy tôi quyết định sử dụng AJAX để gửi biểu mẫu và chuyển hướng nó đến trang tôi cần, tuy nhiên, tôi gặp lỗi này trên trình duyệt của mình:

Nội dung hỗn hợp: Trang tại ' https://page.com ' đã được tải qua HTTPS, nhưng đã yêu cầu điểm cuối XMLHttpRequest không an toàn ' http://XX.XXX.XX.XXX/vicidial/non_agent_api.php?queries=query=data '. Yêu cầu này đã bị chặn; nội dung phải được phân phát qua HTTPS.

Đây là tập lệnh AJAX của tôi:

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

Chỉ đặt https trong URL sẽ không hoạt động, có cách nào để tôi có thể gửi dữ liệu qua GET và chuyển hướng người dùng đến trang thankyou của tôi không?

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

Vấn đề ở đây là nội dung hỗn hợp, điều này có nghĩa là tôi đã tải một trang thông qua HTTPS và đang cố truy cập qua AJAX một API có trong HTTP. Nhưng trình duyệt sẽ không cho phép chúng tôi làm điều đó.

Vì vậy, nếu bạn không thể đặt API thành HTTPS (đây là trường hợp của tôi), chúng tôi vẫn có thể tiếp cận điều này theo một cách khác.

Vấn đề chính không phải là vấn đề nội dung hỗn hợp mà là tôi muốn gửi dữ liệu tới một API và chuyển hướng người dùng đến một trang cảm ơn ưa thích. Thay vì sử dụng AJAX, tôi đã tạo một tệp php nhận dữ liệu sẽ gửi dữ liệu đó bằng cách sử dụng curl tới API (vì điều này đang được thực hiện ở phía máy chủ nên không có vấn đề về nội dung hỗn hợp) và chuyển hướng người dùng hạnh phúc của tôi đến một trang cảm ơn lạ mắt.


Bạn có phiên bản API an toàn của mình không? Bạn sẽ cần yêu cầu qua HTTPS nếu bạn đang sử dụng một trang web an toàn làm nguồn gốc.
Cameron Tinker

1
Không, tôi không, có cách nào khác mà tôi có thể làm được không? Ý tôi là yêu cầu sẽ được thực hiện nếu chỉ sử dụng biểu mẫu gửi mà không có Ajax
StormRage

Bạn có thể tạo một URL HTTPS trong Apache để proxy XX.XXX.XX.XXqua HTTP. Tuy nhiên, nếu mục đích của HTTP là bảo vệ thông tin của người dùng, bạn sẽ cần phải cẩn thận rằng tuyến đường giữa các máy chủ không đi qua internet công cộng.
halfer

Câu trả lời:


89

Nếu bạn tải một trang trong trình duyệt của mình bằng HTTPS, trình duyệt sẽ từ chối tải bất kỳ tài nguyên nào qua HTTP. Như bạn đã thử, việc thay đổi URL API để có HTTPS thay vì HTTP thường giải quyết được vấn đề này . Tuy nhiên, API của bạn không được cho phép kết nối HTTPS. Do đó, bạn phải buộc HTTP trên trang chính hoặc yêu cầu họ cho phép kết nối HTTPS.

Lưu ý về điều này: Yêu cầu sẽ vẫn hoạt động nếu bạn truy cập URL API thay vì cố gắng tải nó bằng AJAX. Điều này là do trình duyệt không tải tài nguyên từ bên trong một trang bảo mật, thay vào đó nó đang tải một trang không an toàn và nó chấp nhận điều đó. Tuy nhiên, để nó có sẵn thông qua AJAX, các giao thức phải phù hợp.


1
Được rồi, api có trong máy chủ của tôi, tôi có thể làm theo hướng dẫn nào để tạo https không?
StormRage

1
@StormRage Hoàn toàn có thể! Bạn đang chạy loại máy chủ nào? Apache? Đó là lưu trữ được chia sẻ hay máy chủ riêng?
Mikel Bitson

@StormRage Vui lòng cho tôi biết nếu bạn cần hỗ trợ thêm. Nếu không, việc bỏ phiếu sẽ khuyến khích sự hỗ trợ công cộng mà bạn nhận được trên SO.
Mikel Bitson

1
Xin lỗi vì đã đến muộn, tôi đã giải quyết được nó mà không sử dụng AJAX, các giải pháp của tôi bao gồm một số hàm wordpress / php curl, tôi sẽ đăng giải pháp của mình ngay khi có thể, tôi có nên chỉnh sửa câu hỏi và viết giải pháp của mình vào đó không, hoặc tôi có nên sử dụng nút có nội dung "trả lời câu hỏi của riêng bạn" không?
StormRage

1
Đánh dấu phần có liên quan của câu trả lời ở đây. Giải pháp duy nhất thực tế vấn đề này là sử dụng HTTPS
Liam

129

Tôi đã giải quyết vấn đề này bằng cách thêm mã sau vào trang HTML, vì chúng tôi đang sử dụng API của bên thứ ba không do chúng tôi kiểm soát.

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

Hy vọng điều này sẽ giúp ích, và cho một kỷ lục.


8
Điều này nâng cấp tất cả các httpyêu cầu sử dụng https, vì vậy bạn không cần phải thay đổi giao thức cho mỗi cuộc gọi.
phát hành

3
Điều này làm việc với tôi, nhưng rất tiếc là điều này không hoạt động với Internet Explorer: developer.mozilla.org/en-US/docs/Web/HTTP/Headers/…
Ciaran Gallagher vào

2
Tôi đã thử điều này nhưng bây giờ tôi đang gặp lỗi CORS trên firefox và net :: ERR_SSL_PROTOCOL_ERROR trên chrome. tôi biết tất cả các cuộc gọi đều hoạt động vì trang web của tôi trước đây là http nhưng bây giờ tôi đã đổi thành https, các cuộc gọi này không hoạt động. có cách nào khác mà tôi có thể thêm vào tệp html chính của mình không? Bởi vì nếu tôi làm theo các bước @Juanma Menendez thì tất cả các cuộc gọi đều hoạt động nhưng tôi không thể mong đợi mọi người dùng làm điều này.
Otorrinororsologista -man

Tôi đã đấu tranh với vấn đề này trong nhiều giờ cho đến khi tôi tìm thấy câu trả lời của bạn, cảm ơn rất nhiều!
Muhab,

Chúng tôi xác nhận rằng giải pháp này phù hợp với trường hợp của chúng tôi, chỉ có thể sẽ giúp bạn trong tương lai: Chúng tôi đã cố gắng thiết lập tính năng phát trực tiếp / video theo yêu cầu HTTP được phân đoạn, giống như vậy www.example.com/blabla/master.m3u8. Tất cả đều hoạt động tốt trên http. Nhưng khi chúng tôi di chuyển nó sang https, nó sẽ không hoạt động. Chúng tôi phát hiện ra rằng phần đầu master.m3u8có thể thực hiện httpsyêu cầu, nhưng đoạn video được phân đoạn sau luôn sử dụng http(vì chúng tôi đang sử dụng mô-đun của bên thứ ba). Không có vấn đề gì chúng tôi chỉnh sửa nó sẽ không sử dụng https. Đã sử dụng chính sách này và hoạt động ngay lập tức như một sự quyến rũ!
rahmatns

34

Nếu bạn chỉ đang truy cập một trang web mà bạn tin tưởng và bạn muốn tiến nhanh, chỉ cần:

1- Nhấp vào biểu tượng chiếc khiên ở ngoài cùng bên phải của thanh địa chỉ.

Cho phép nội dung hỗn hợp trong Google Chrome

2- Trong cửa sổ bật lên, nhấp vào "Vẫn tải" hoặc "Tải tập lệnh không an toàn" (tùy thuộc vào phiên bản Chrome của bạn).


Nếu bạn muốn đặt trình duyệt Chrome của mình LUÔN LUÔN (trong tất cả các trang web) cho phép nội dung hỗn hợp:

1- Trong trình duyệt Chrome đang mở, nhấn Ctrl + Shift + Q trên bàn phím của bạn để buộc đóng Chrome. Chrome phải được đóng hoàn toàn trước khi thực hiện các bước tiếp theo.

2- Nhấp chuột phải vào biểu tượng màn hình Google Chrome (hoặc liên kết Start Menu). Chọn Thuộc tính.

3- Ở cuối thông tin hiện có trong trường Mục tiêu, hãy thêm: "--allow-running-secure-content" (Có một khoảng trắng trước dấu gạch ngang đầu tiên.)

4- Bấm OK.

5- Mở Chrome và thử khởi chạy nội dung đã bị chặn trước đó. Nó sẽ hoạt động ngay bây giờ.


4
Điều này không có tác dụng gì đối với những người thiết kế trang web đối với những người dùng không muốn thay đổi cài đặt của họ để làm cho trang web hoạt động trên trình duyệt của họ, chẳng hạn như OP.
smallpants

12

Lý do cho lỗi này rất đơn giản. AJAX của bạn đang cố gắng gọi qua HTTP trong khi máy chủ của bạn đang chạy qua HTTPS, vì vậy máy chủ của bạn đang từ chối gọi AJAX của bạn. Điều này có thể được khắc phục bằng cách thêm dòng sau vào bên trong thẻ head của tệp HTML chính của bạn:

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

nó cho phép nó nhưng yêu cầu là https
BG BRUNO

Trong trường hợp của tôi. máy chủ chỉ yêu cầu HTTP. Tôi thử cái này <meta> không được. Trình duyệt báo lỗi yêu cầu tại URL.
iHad 169

1

Nếu mã API của bạn đang chạy trên máy chủ node.js thì bạn cần tập trung sự chú ý của mình vào đó, không phải trong Apache hoặc NGINX. Mikel nói đúng, việc thay đổi URL API thành HTTPS là câu trả lời nhưng nếu API của bạn đang gọi máy chủ node.js, thì tốt hơn nên thiết lập cho HTTPS! Và tất nhiên, máy chủ node.js có thể nằm trên bất kỳ cổng nào không sử dụng, nó không nhất thiết phải là cổng 443.


API là của bên thứ ba, vì vậy không có cách nào tôi có thể đặt nó thành https và như bạn có thể thấy trong url mà tôi đang cố gắng truy cập, API được mã hóa bằng PHP
StormRage

@StormRage Câu hỏi của bạn và câu trả lời của Mikel đã dẫn đến giải pháp cho vấn đề của tôi, vì vậy tôi nghĩ rằng tôi sẽ ghi chú nó ở đây mặc dù câu trả lời của tôi không thực sự áp dụng cho tình huống của bạn.
mcmacerson

Chà, bạn và Mikel nói đúng, giải pháp hợp lý nhất sẽ là sử dụng ssl trong API, nhưng trong bối cảnh này, tôi không thể làm điều đó vì nó là API của bên thứ 3, nhưng là giải pháp cho ppl sử dụng wordpress hoặc bất kỳ trang web kế thừa nào có thể đang gửi dữ liệu đến chương trình phụ trợ của họ và gửi yêu cầu đến API trong máy chủ.
StormRage

tôi đã triển khai api bởi laravel dưới dạng phía máy chủ và ứng dụng ion là PWA trên cùng một máy chủ lưu trữ nên tôi gặp lỗi tương tự được đề cập trong bài viết này stackoverflow.com/q/56157129/308578
saber tabatabaee yazdi

1

Thay vì sử dụng phương pháp Ajax Post, bạn có thể sử dụng biểu mẫu động cùng với phần tử. Nó sẽ hoạt động ngay cả khi trang được tải bằng SSL và nguồn đã gửi không phải SSL.

Bạn cần đặt giá trị giá trị của phần tử của biểu mẫu.

Trên thực tế, biểu mẫu động mới sẽ mở ở chế độ không SSL trong tab riêng của Trình duyệt khi thuộc tính mục tiêu đã đặt '_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()

Tôi thực sự muốn truy cập một API, nhưng khi tôi làm điều đó với phương pháp của bạn bằng cách đưa ra yêu cầu nhận, tôi thực sự sẽ gửi một biểu mẫu nhưng bây giờ tôi đang gặp khó khăn với việc đọc phản hồi từ API. Vì tôi đoán rằng AJAX hoặc xmlhttprequest là lựa chọn duy nhất
Siddharth Choudhary

giải pháp liên quan :-)
BG BRUNO

đơn giản và rực rỡ
Harkal

0

Tôi đã gặp vấn đề tương tự, nhưng đối với tôi vấn đề là lệnh xây dựng. Tôi đang thực hiện "ng build --prod". Tôi đã sửa nó thành "ng build --prod --base-href / applicationname /". và điều này đã giải quyết được vấn đề của tôi.


0

trong trường hợp của tôi, localhost của tôi là httpvà phiên bản đã triển khai của tôi là https, vì vậy tôi đã sử dụng tập lệnh này để thêm thẻ meta http-equiv chỉ cho 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)
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.