กำลังโหลดปลายทางข้ามโดเมนด้วย AJAX


132

ฉันกำลังพยายามโหลดหน้า HTML ข้ามโดเมนโดยใช้ AJAX แต่เว้นแต่ว่า dataType เป็น "jsonp" ฉันไม่ได้รับคำตอบ อย่างไรก็ตามการใช้ jsonp เบราว์เซอร์คาดหวังประเภท mime ของสคริปต์ แต่ได้รับ "text / html"

รหัสของฉันสำหรับคำขอคือ:

$.ajax({
    type: "GET",
    url: "http://saskatchewan.univ-ubs.fr:8080/SASStoredProcess/do?_username=DARTIES3-2012&_password=P@ssw0rd&_program=%2FUtilisateurs%2FDARTIES3-2012%2FMon+dossier%2Fanalyse_dc&annee=2012&ind=V&_action=execute",
    dataType: "jsonp",
}).success( function( data ) {
    $( 'div.ajax-field' ).html( data );
});

มีวิธีหลีกเลี่ยงการใช้ jsonp สำหรับคำขอหรือไม่? ฉันได้ลองใช้พารามิเตอร์ crossDomain แล้ว แต่ไม่ได้ผล

หากไม่มีวิธีใดในการรับเนื้อหา html ใน jsonp? ขณะนี้คอนโซลกำลังพูดว่า "ไม่คาดคิด <" ในการตอบกลับ jsonp


1
ฉันได้แก้ไขปัญหาโดยสร้าง proxy.php ตามที่อธิบายไว้ที่นี่scode7.blogspot.com/2019/11/…
CodeDezk

ขอบคุณ CodeDezk ฉันสร้างพร็อกซี PHP ของตัวเองสำหรับคำขอ AJAX ข้ามโดเมนตามลิงค์ของคุณ มันง่ายมาก
GTS Joe

คำตอบ:


236

jQuery Ajax Notes

  • เนื่องจากข้อ จำกัด ของการรักษาความปลอดภัยเบราว์เซอร์ส่วนใหญ่อาแจ็กซ์คำขออยู่ภายใต้นโยบายกำเนิดเดียวกัน ; คำขอไม่สามารถดึงข้อมูลจากโดเมนโดเมนย่อยพอร์ตหรือโปรโตคอลอื่นได้สำเร็จ
  • คำขอสคริปต์และ JSONP ไม่อยู่ภายใต้ข้อ จำกัด ของนโยบายต้นทางเดียวกัน

มีบางวิธีในการเอาชนะอุปสรรคข้ามโดเมน :

มีปลั๊กอินบางตัวที่ช่วยในการร้องขอข้ามโดเมน :

โปรดทราบ!

วิธีที่ดีที่สุดในการแก้ไขปัญหานี้คือการสร้างพร็อกซีของคุณเองในส่วนหลังเพื่อให้พร็อกซีของคุณชี้ไปที่บริการในโดเมนอื่นเนื่องจากในส่วนหลังไม่มีข้อ จำกัด ของนโยบายต้นทางเดียวกัน แต่ถ้าคุณไม่สามารถทำได้ในส่วนหลังให้ใส่ใจกับเคล็ดลับต่อไปนี้


คำเตือน!

โดยใช้พร็อกซีของบุคคลที่สามไม่ได้มีการปฏิบัติที่เชื่อถือได้เพราะพวกเขาสามารถติดตามข้อมูลของคุณเพื่อที่จะสามารถนำมาใช้กับข้อมูลสาธารณะ แต่ไม่เคยมีข้อมูลส่วนตัว


ตัวอย่างโค้ดที่แสดงด้านล่างใช้jQuery.get ()และjQuery.getJSON ()ทั้งสองเป็นวิธีการชวเลขของjQuery.ajax ()


CORS ได้ทุกที่

CORS Anywhere เป็นพร็อกซี node.jsซึ่งเพิ่มส่วนหัว CORS ให้กับคำขอพร็อกซี
ในการใช้ API เพียงนำหน้า URL ด้วย URL ของ API (รองรับhttps : ดูที่เก็บ github )

หากคุณต้องการเปิดใช้งานคำขอข้ามโดเมนโดยอัตโนมัติเมื่อจำเป็นให้ใช้ข้อมูลโค้ดต่อไปนี้:

$.ajaxPrefilter( function (options) {
  if (options.crossDomain && jQuery.support.cors) {
    var http = (window.location.protocol === 'http:' ? 'http:' : 'https:');
    options.url = http + '//cors-anywhere.herokuapp.com/' + options.url;
    //options.url = "http://cors.corsproxy.io/url=" + options.url;
  }
});

$.get(
    'http://en.wikipedia.org/wiki/Cross-origin_resource_sharing',
    function (response) {
        console.log("> ", response);
        $("#viewer").html(response);
});


ต้นกำเนิดอะไรก็ตาม

ไม่ว่า Originคือการเข้าถึงjsonp ข้ามโดเมน นี้เป็นทางเลือกที่มาเปิดให้anyorigin.com

ในการดึงข้อมูลจากgoogle.comคุณสามารถใช้ข้อมูลโค้ดนี้:

// It is good specify the charset you expect.
// You can use the charset you want instead of utf-8.
// See details for scriptCharset and contentType options: 
// http://api.jquery.com/jQuery.ajax/#jQuery-ajax-settings
$.ajaxSetup({
    scriptCharset: "utf-8", //or "ISO-8859-1"
    contentType: "application/json; charset=utf-8"
});

$.getJSON('http://whateverorigin.org/get?url=' + 
    encodeURIComponent('http://google.com') + '&callback=?',
    function (data) {
        console.log("> ", data);

        //If the expected response is text/plain
        $("#viewer").html(data.contents);

        //If the expected response is JSON
        //var response = $.parseJSON(data.contents);
});


CORS Proxy

CORS Proxy เป็นพร็อกซี node.js ที่เรียบง่ายเพื่อเปิดใช้งานการร้องขอ CORS สำหรับเว็บไซต์ใด ๆ ช่วยให้โค้ดจาวาสคริปต์บนไซต์ของคุณเข้าถึงทรัพยากรบนโดเมนอื่น ๆ ที่ปกติจะถูกบล็อกเนื่องจากนโยบายแหล่งกำเนิดเดียวกัน

มันทำงานอย่างไร? CORS Proxy ใช้ประโยชน์จาก Cross-Origin Resource Sharing ซึ่งเป็นคุณลักษณะที่เพิ่มเข้ามาพร้อมกับ HTML 5 เซิร์ฟเวอร์สามารถระบุได้ว่าต้องการให้เบราว์เซอร์อนุญาตให้เว็บไซต์อื่นร้องขอทรัพยากรที่โฮสต์ได้ CORS Proxy เป็นเพียง HTTP Proxy ที่เพิ่มส่วนหัวให้กับคำตอบที่ระบุว่า "ทุกคนสามารถร้องขอได้"

นี่เป็นอีกวิธีหนึ่งในการบรรลุเป้าหมาย (ดูwww.corsproxy.com ) สิ่งที่คุณต้องทำคือตัดhttp: //และwww. จาก URL ที่พร็อกซีและนำหน้า URL ด้วยwww.corsproxy.com/

$.get(
    'http://www.corsproxy.com/' +
    'en.wikipedia.org/wiki/Cross-origin_resource_sharing',
    function (response) {
        console.log("> ", response);
        $("#viewer").html(response);
});


CORS พร็อกซีเบราว์เซอร์

เมื่อเร็ว ๆ นี้ฉันพบสิ่งนี้มันเกี่ยวข้องกับยูทิลิตี้ Cross Origin Remote Sharing ด้านความปลอดภัย แต่เป็นกล่องดำที่มี Flash เป็นแบ็กเอนด์

คุณสามารถดูการทำงานได้ที่นี่: CORS proxy browser
รับซอร์สโค้ดบน GitHub: koto / cors-proxy-browser


4
คุณยังสามารถปรับใช้ WhateverOrigin.org เวอร์ชันของคุณเอง (หรือพอร์ตโค้ดเพื่อใช้งานของคุณเอง) จากที่นี่: github.com/ripper234/Whatever-Origin
EpicVoyage

1
รูปภาพ CSS และจาวาสคริปต์ภายนอกสามารถอ้างอิงได้จากจุดเริ่มต้นอื่นดังนั้นในการตอบสนองคุณสามารถไปที่สตริง HTML และแทนที่ src ของทรัพยากรภายนอก
jherax

1
สวัสดี jherax ฉันใช้ whatorigin เพื่อรับหน้า html (วิธีเดียวที่ใช้ได้กับฉันใช้ yql, google ฯลฯ ) แต่ตัวอักษรที่ไม่ใช่ภาษาอังกฤษนั้นแปลก พยายามเข้ารหัส data.contents แต่ไม่ได้รับการช่วยเหลือ
user217648

1
สวัสดี @Miru ตามชื่อเรื่อง: "กำลังโหลดหน้า html ข้ามโดเมนด้วย jQuery AJAX" ฉันตอบชื่อเรื่องโดยให้ตัวอย่างบางส่วนโดยใช้พร็อกซีเพื่อดำเนินการขอข้ามโดเมน นอกจากนี้เพื่อตอบสนองต่อถ้อยคำของคำถามฉันได้จัดเตรียมลิงก์เพื่อส่งคำขอข้ามโดเมนโดยใช้ JSONP กับ YQL ฉันขอเชิญคุณอ่านลิงค์เหล่านี้มีประโยชน์มาก
jherax

1
จบลงด้วยการใช้วิธี CORS Anywhere ด้วย$.ajaxPrefilterและมันก็ใช้งานได้ดี ขอบคุณมาก!
Joshua Pinter

24

คุณสามารถใช้ปลั๊กอิน jQuery ของ Ajax-cross-origin ด้วยปลั๊กอินนี้คุณใช้jQuery.ajax()ข้ามโดเมน ใช้บริการของ Google เพื่อให้บรรลุสิ่งนี้:

ปลั๊กอิน AJAX Cross Origin ใช้ Google Apps Script เป็นพร็อกซี jSON getter โดยที่ jSONP ไม่ได้ใช้งาน เมื่อคุณตั้งค่าตัวเลือก crossOrigin เป็นจริงปลั๊กอินจะแทนที่ URL เดิมด้วยที่อยู่ Google Apps Script และส่งเป็นพารามิเตอร์ URL ที่เข้ารหัส Google Apps Script ใช้ทรัพยากรของ Google Servers เพื่อรับข้อมูลระยะไกลและส่งคืนกลับไปยังไคลเอ็นต์เป็น JSONP

ใช้งานง่ายมาก:

    $.ajax({
        crossOrigin: true,
        url: url,
        success: function(data) {
            console.log(data);
        }
    });

สามารถอ่านเพิ่มเติมได้ที่นี่: http://www.ajax-cross-origin.com/


22
เท่าที่ฉันกังวลปลั๊กอินนี้ไม่เคยใช้งานได้ มันไม่ได้ทำอะไรบน Chrome
Michael

ฉันจะตรวจสอบสิทธิ์กับเซิร์ฟเวอร์ได้อย่างไร?
sttaq

ใช้งานได้ดี! API ที่ฉันใช้ไม่รองรับทั้ง JSONP หรือ CORS ดังนั้นนี่คือสิ่งเดียวที่ใช้ได้ผล ขอบคุณมาก!
JP Lew

crossOriginตัวเลือกของ jQuery ไม่ได้ทำอะไรเพื่อลดนโยบายที่มาเดียวกันอย่างแน่นอน ฉันจะลบคำตอบนี้ถ้าทำได้
Phil

13

หากไซต์ภายนอกไม่รองรับ JSONP หรือ CORS ตัวเลือกเดียวของคุณคือใช้พร็อกซี

สร้างสคริปต์บนเซิร์ฟเวอร์ของคุณที่ร้องขอเนื้อหานั้นจากนั้นใช้ jQuery ajax เพื่อตีสคริปต์บนเซิร์ฟเวอร์ของคุณ


5

เพียงใส่สิ่งนี้ในส่วนหัวของหน้า PHP ของคุณและมันก็ใช้งานไม่ได้หากไม่มี API:

header('Access-Control-Allow-Origin: *'); //allow everybody  

หรือ

header('Access-Control-Allow-Origin: http://codesheet.org'); //allow just one domain 

หรือ

$http_origin = $_SERVER['HTTP_ORIGIN'];  //allow multiple domains

$allowed_domains = array(
  'http://codesheet.org',
  'http://stackoverflow.com'
);

if (in_array($http_origin, $allowed_domains))
{  
    header("Access-Control-Allow-Origin: $http_origin");
}

ฉันสงสัยว่า$_SERVER['HTTP_ORIGIN']มาจากไหน ไม่พบในเอกสาร PHP หรือที่อื่น
Zsolti

อืมดูเหมือนว่าจะมีเฉพาะคำขอ AJAX เท่านั้น อย่างไรก็ตามขอบคุณสำหรับคำตอบ
Zsolti

0

ฉันโพสต์สิ่งนี้เผื่อว่ามีคนประสบปัญหาเดียวกันกับที่ฉันกำลังเผชิญอยู่ตอนนี้ ฉันมีเครื่องพิมพ์ความร้อน Zebra พร้อมกับเซิร์ฟเวอร์การพิมพ์ ZebraNet ซึ่งมีอินเทอร์เฟซผู้ใช้ที่ใช้ HTML สำหรับการแก้ไขการตั้งค่าต่างๆการดูสถานะปัจจุบันของเครื่องพิมพ์ ฯลฯ ฉันต้องการรับสถานะของเครื่องพิมพ์ซึ่งจะปรากฏขึ้น ในหนึ่งในเพจ html ที่นำเสนอโดยเซิร์ฟเวอร์ ZebraNet และตัวอย่างเช่น alert () ข้อความถึงผู้ใช้ในเบราว์เซอร์ ซึ่งหมายความว่าฉันต้องได้รับหน้า html นั้นใน Javascript ก่อน แม้ว่าเครื่องพิมพ์จะอยู่ใน LAN ของพีซีของผู้ใช้นโยบายแหล่งกำเนิดเดียวกันนั้นยังคงอยู่อย่างมั่นคงในทางของฉัน ฉันลองใช้ JSONP แต่เซิร์ฟเวอร์ส่งคืน html และฉันไม่พบวิธีแก้ไขการทำงานของมัน (ถ้าทำได้ฉันจะตั้งค่าส่วนหัวมายากล Access-control-allow-origin: *) ผมจึงตัดสินใจเขียนแอปคอนโซลเล็ก ๆ ใน C # จะต้องถูกเรียกใช้ในฐานะผู้ดูแลระบบเพื่อให้ทำงานได้อย่างถูกต้องมิฉะนั้นจะหมุนรอบ: D ข้อยกเว้น นี่คือรหัสบางส่วน:

// Create a listener.
        HttpListener listener = new HttpListener();
        // Add the prefixes.
        //foreach (string s in prefixes)
        //{
        //    listener.Prefixes.Add(s);
        //}
        listener.Prefixes.Add("http://*:1234/"); // accept connections from everywhere,
        //because the printer is accessible only within the LAN (no portforwarding)
        listener.Start();
        Console.WriteLine("Listening...");
        // Note: The GetContext method blocks while waiting for a request. 
        HttpListenerContext context;
        string urlForRequest = "";

        HttpWebRequest requestForPage = null;
        HttpWebResponse responseForPage = null;
        string responseForPageAsString = "";

        while (true)
        {
            context = listener.GetContext();
            HttpListenerRequest request = context.Request;
            urlForRequest = request.RawUrl.Substring(1, request.RawUrl.Length - 1); // remove the slash, which separates the portNumber from the arg sent
            Console.WriteLine(urlForRequest);

            //Request for the html page:
            requestForPage = (HttpWebRequest)WebRequest.Create(urlForRequest);
            responseForPage = (HttpWebResponse)requestForPage.GetResponse();
            responseForPageAsString = new StreamReader(responseForPage.GetResponseStream()).ReadToEnd();

            // Obtain a response object.
            HttpListenerResponse response = context.Response;
            // Send back the response.
            byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseForPageAsString);
            // Get a response stream and write the response to it.
            response.ContentLength64 = buffer.Length;
            response.AddHeader("Access-Control-Allow-Origin", "*"); // the magic header in action ;-D
            System.IO.Stream output = response.OutputStream;
            output.Write(buffer, 0, buffer.Length);
            // You must close the output stream.
            output.Close();
            //listener.Stop();

สิ่งที่ผู้ใช้ต้องทำคือเรียกใช้แอปคอนโซลในฐานะผู้ดูแลระบบ ฉันรู้ว่ามันเป็นวิธีที่เหมือนกัน ... น่าผิดหวังและซับซ้อน แต่เป็นวิธีแก้ปัญหาชั่วคราวสำหรับปัญหานโยบายโดเมนในกรณีที่คุณไม่สามารถแก้ไขเซิร์ฟเวอร์ได้ไม่ว่าด้วยวิธีใดก็ตาม

แก้ไข: จาก js ฉันโทร ajax ง่ายๆ:

$.ajax({
                type: 'POST',
                url: 'http://LAN_IP:1234/http://google.com',
                success: function (data) {
                    console.log("Success: " + data);
                },
                error: function (e) {
                    alert("Error: " + e);
                    console.log("Error: " + e);
                }
            });

html ของเพจที่ร้องขอจะถูกส่งคืนและเก็บไว้ในตัวแปรข้อมูล


0

ในการรับรูปแบบข้อมูลจากไซต์ภายนอกโดยการส่งผ่านโดยใช้ local proxy ตามที่ jherax แนะนำคุณสามารถสร้างเพจ php ที่ดึงเนื้อหามาให้คุณจาก url ภายนอกที่เกี่ยวข้องและส่งคำขอ get ไปยังเพจ php นั้นได้

var req = new XMLHttpRequest();
req.open('GET', 'http://localhost/get_url_content.php',false);
if(req.status == 200) {
   alert(req.responseText);
}

เป็นพร็อกซี php คุณสามารถใช้https://github.com/cowboy/php-simple-proxy


0

URLวันนี้คุณใช้งานไม่ได้ แต่รหัสของคุณสามารถอัปเดตด้วยโซลูชันการทำงานนี้:

var url = "http://saskatchewan.univ-ubs.fr:8080/SASStoredProcess/do?_username=DARTIES3-2012&_password=P@ssw0rd&_program=%2FUtilisateurs%2FDARTIES3-2012%2FMon+dossier%2Fanalyse_dc&annee=2012&ind=V&_action=execute";

url = 'https://google.com'; // TEST URL

$.get("https://images"+~~(Math.random()*33)+"-focus-opensocial.googleusercontent.com/gadgets/proxy?container=none&url=" + encodeURI(url), function(data) {
    $('div.ajax-field').html(data);
});
<div class="ajax-field"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>


-2

คุณจำเป็นต้องมีพร็อกซี่ล ธ ซึ่งผู้รับมอบฉันทะตามคำขอของคุณจากเบราว์เซอร์ของคุณเพื่อการบริการที่ร้องขอเหมาะสมกับส่วนหัวของลรายชื่อบริการดังกล่าวอยู่ในข้อมูลโค้ดด้านล่าง คุณยังสามารถเรียกใช้ข้อมูลโค้ดที่ให้มาเพื่อดู ping ไปยังบริการดังกล่าวจากตำแหน่งของคุณ

$('li').each(function() {
  var self = this;
  ping($(this).text()).then(function(delta) {
    console.log($(self).text(), delta, ' ms');
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.rawgit.com/jdfreder/pingjs/c2190a3649759f2bd8569a72ae2b597b2546c871/ping.js"></script>
<ul>
  <li>https://crossorigin.me/</li>
  <li>https://cors-anywhere.herokuapp.com/</li>
  <li>http://cors.io/</li>
  <li>https://cors.5apps.com/?uri=</li>
  <li>http://whateverorigin.org/get?url=</li>
  <li>https://anyorigin.com/get?url=</li>
  <li>http://corsproxy.nodester.com/?src=</li>
  <li>https://jsonp.afeld.me/?url=</li>
  <li>http://benalman.com/code/projects/php-simple-proxy/ba-simple-proxy.php?url=</li>
</ul>


11
นี่ไม่ได้ตอบคำถาม แต่อย่างใด
0xc0de

@ 0xc0de ในที่สุดฉันก็ได้เขียนคำตอบแล้ว
galeksandrp

-7

คิดออก ใช้สิ่งนี้แทน

$('.div_class').load('http://en.wikipedia.org/wiki/Cross-origin_resource_sharing #toctitle');

รหัสที่คุณใช้นั้นไม่เกี่ยวข้อง สิ่งที่สำคัญคือส่วนหัว CORS ฝั่งเซิร์ฟเวอร์
Quentin
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.