“ เนื้อหาผสมถูกบล็อก” เมื่อเรียกใช้การดำเนินการ 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 หากคุณใช้ไซต์ที่ปลอดภัยเป็นต้นกำเนิด
Cameron Tinker

1
ไม่ฉันทำไม่ได้มีวิธีอื่นที่ฉันสามารถทำได้หรือไม่? ฉันหมายถึงคำขอจะผ่านไปหากใช้แบบฟอร์มส่งโดยไม่มี Ajax
StormRage

คุณสามารถสร้าง URL HTTPS ใน Apache เพื่อพร็อกซีXX.XXX.XX.XXผ่าน HTTP อย่างไรก็ตามหากจุดประสงค์ของ HTTP คือการปกป้องข้อมูลของผู้ใช้คุณจะต้องระมัดระวังว่าเส้นทางระหว่างเซิร์ฟเวอร์ไม่ผ่านอินเทอร์เน็ตสาธารณะ
แขวนคอ

คำตอบ:


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
Liam

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/…
Ciaran Gallagher

2
ฉันได้ลองแล้ว แต่ตอนนี้ฉันได้รับข้อผิดพลาด CORS บน firefox และ net :: ERR_SSL_PROTOCOL_ERROR บน chrome ฉันรู้ว่าการโทรทั้งหมดทำงานได้เนื่องจากหน้าเว็บของฉันเคยเป็น http มาก่อน แต่ตอนนี้ฉันเปลี่ยนเป็น https การโทรเหล่านี้ไม่ทำงาน มีสิ่งอื่นใดที่ฉันสามารถเพิ่มลงในไฟล์ html หลักของฉันได้บ้าง เพราะถ้าฉันทำตามขั้นตอนของ @Juanma Menendez ทุกสายก็ใช้ได้ แต่ฉันคาดหวังให้ผู้ใช้ทุกคนทำสิ่งนี้ไม่ได้
Otorrinolaringologista -man

ฉันต่อสู้กับปัญหานี้มาหลายชั่วโมงจนพบคำตอบของคุณขอบคุณมาก!
Muhab

เราขอยืนยันว่าการแก้ปัญหานี้ทำงานในกรณีของเราแค่บางทีจะช่วยให้คุณมากเกินไปในอนาคตเราพยายามที่จะสร้างการแบ่ง 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- ในตอนท้ายของข้อมูลที่มีอยู่ในช่อง Target ให้เพิ่ม: "--allow-running-insecure-content" (มีช่องว่างก่อนขีดแรก)

4- คลิกตกลง

5- เปิด Chrome และพยายามเปิดเนื้อหาที่ถูกบล็อกก่อนหน้านี้ ตอนนี้ควรใช้งานได้แล้ว


4
สิ่งนี้ไม่ได้ทำอะไรสำหรับผู้ที่ออกแบบเว็บไซต์สำหรับผู้ใช้ที่ไม่ต้องการเปลี่ยนการตั้งค่าเพื่อให้ไซต์ทำงานบนเบราว์เซอร์ของตนเช่น OP
smallpants

13

สาเหตุของข้อผิดพลาดนี้ง่ายมาก AJAX ของคุณพยายามเรียกผ่าน HTTP ในขณะที่เซิร์ฟเวอร์ของคุณกำลังทำงานผ่าน HTTPS ดังนั้นเซิร์ฟเวอร์ของคุณจึงปฏิเสธการเรียก AJAX ของคุณ ซึ่งสามารถแก้ไขได้โดยเพิ่มบรรทัดต่อไปนี้ภายใน head tag ของไฟล์ 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 Mikel พูดถูกการเปลี่ยน URL API เป็น HTTPS คือคำตอบ แต่ถ้า API ของคุณเรียกเซิร์ฟเวอร์ node.js ควรตั้งค่า HTTPS ให้ดีขึ้น! และแน่นอนว่าเซิร์ฟเวอร์ node.js สามารถอยู่บนพอร์ตใดก็ได้ที่ไม่ได้ใช้งานไม่จำเป็นต้องเป็นพอร์ต 443


API เป็นของบุคคลที่สามดังนั้นจึงไม่มีทางที่ฉันจะตั้งค่าเป็น https ได้และอย่างที่คุณเห็นใน url ที่ฉันพยายามจะตี API ถูกเข้ารหัสใน PHP
StormRage

@StormRage คำถามของคุณและคำตอบของ Mikel นำไปสู่การแก้ปัญหาของฉันดังนั้นฉันคิดว่าฉันจะจดบันทึกไว้ที่นี่แม้ว่าคำตอบของฉันจะไม่ตรงกับสถานการณ์ของคุณก็ตาม
mcmacerson

คุณและ Mikel พูดถูกวิธีแก้ปัญหาที่เหมาะสมที่สุดคือการใช้ ssl ใน API แต่ในบริบทนี้ฉันไม่สามารถทำเช่นนั้นได้เนื่องจากเป็น API ของบุคคลที่สาม แต่เป็นโซลูชันสำหรับ ppl โดยใช้ wordpress หรือ ไซต์เดิมใด ๆ สามารถส่งข้อมูลไปยังแบ็กเอนด์และส่งคำขอไปยัง API ภายในเซิร์ฟเวอร์
StormRage

ฉันใช้ api โดย laravel เป็นฝั่งเซิร์ฟเวอร์และแอปพลิเคชันไอออนิกเป็น PWA บนโฮสต์เดียวกันดังนั้นฉันจึงมีข้อผิดพลาดเดียวกันกับที่กล่าวถึงในบทความนี้stackoverflow.com/q/56157129/308578
saber tabatabaee yazdi

1

แทนที่จะใช้วิธี Ajax Post คุณสามารถใช้รูปแบบไดนามิกร่วมกับองค์ประกอบได้ มันจะใช้งานได้แม้เพจจะโหลดใน SSL และแหล่งที่มาที่ส่งไม่ใช่ SSL

คุณต้องกำหนดมูลค่าขององค์ประกอบของรูปแบบ

รูปแบบไดนามิกใหม่จริงจะเปิดเป็นโหมดที่ไม่ใช่ 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()

จริงๆแล้วฉันต้องการตี API แต่เมื่อฉันทำตามวิธีการของคุณโดยการร้องขอรับฉันจะส่งแบบฟอร์ม แต่ตอนนี้ฉันติดอยู่กับการอ่านคำตอบกลับจาก API เพราะฉันเดาว่า AJAX หรือ xmlhttprequest เป็นตัวเลือกเดียว
Siddharth Choudhary

intereting solution :-)
BG BRUNO

เรียบง่ายและยอดเยี่ยม
Harkal

0

ฉันเป็นปัญหาเดียวกัน แต่สำหรับฉันปัญหาคือคำสั่ง ng build ฉันกำลังทำ "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)
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.