Завантаження кінцевої точки міждоменного домену за допомогою AJAX


131

Я намагаюся завантажити HTML-сторінку між доменом за допомогою AJAX, але, якщо тип даних не є "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.


Я вирішив проблему, створивши proxy.php, як пояснено тут scode7.blogspot.com/2019/11/…
CodeDezk

Відповіді:


235

jQuery Ajax Notes

  • Через обмеження безпеки веб-переглядача, більшість запитів Ajax підпадає під дію тієї самої політики походження ; запит не може успішно отримати дані з іншого домену, піддомену, порту чи протоколу.
  • На запити сценарію та 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

CORS Proxy - це простий проксі-сервер node.js для включення запиту CORS для будь-якого веб-сайту. Це дозволяє коду Javascript на вашому веб-сайті отримати доступ до ресурсів інших доменів, які зазвичай були б заблоковані через політику того самого походження.

Як це працює? CORS Proxy використовує перевагу крос-походження ресурсів спільного доступу, що є функцією, доданою разом із HTML 5. Сервери можуть вказати, що вони хочуть, щоб браузери дозволяли іншим веб-сайтам запитувати ресурси, на яких вони розміщені. CORS Proxy - це просто HTTP-проксі, який додає заголовок до відповідей, вказуючи, що "кожен може запитати це".

Це ще один спосіб досягнення мети (див. 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
Отримайте вихідний код на GitHub: koto / cors-proxy-browser


4
Ви також можете розгорнути свою власну версію WeverOrigin.org
перенести

1
Зображення, CSS та зовнішній JavaScript можна посилатись з іншого джерела, таким чином, у відповіді ви можете перейти через рядок HTML і замінити src зовнішніх ресурсів
jherax

1
привіт jherax Я використовував whateverorigin, щоб отримати HTML-сторінку (єдиний спосіб працював для мене, використовували yql, google тощо), але не англійські символи дивні. спробував кодувати data.contents, але не допоміг
user217648

1
Привіт @Miru, як говорить заголовок: "Завантаження html-сторінки крос-домену з jQuery AJAX", я відповів на заголовок, надавши кілька прикладів, використовуючи проксі для виконання запитів між доменами. Крім того, у відповідь на формулювання запитання я надав декілька посилань, щоб зробити запити між доменами, використовуючи JSONP з YQL. Запрошую прочитати посилання, вони дуже корисні.
jherax

1
Закінчив за допомогою методу CORS Anywhere за допомогою, $.ajaxPrefilterі він працював чудово. Велике дякую!
Джошуа Пінтер

24

Ви можете використовувати плагін jQuery Ajax-cross-origin. За допомогою цього плагіна ви використовуєте jQuery.ajax()крос-домен. Для цього використовується сервіс Google:

Плагін AJAX Cross Origin використовує сценарій Google Apps як проксі-сервер jSON, де jSONP не реалізований. Коли ви встановите для параметра crossOrigin значення true, плагін замінить оригінальний URL адресою сценарію Google Apps і надішле його як закодований параметр url. Сценарій Google Apps використовує ресурси сервера Google для отримання віддалених даних і повернення їх назад клієнту як JSONP.

Користуватися дуже просто:

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

Більше ви можете прочитати тут: http://www.ajax-cross-origin.com/


22
Наскільки я переживаю, цей плагін ніколи не працював. Це не робить нічого в Chrome.
Майкл

Як я можу пройти автентифікацію на сервері?
sttaq

працює чудово! API, який я використовую, не підтримує ні JSONP, ні CORS, тому це єдине, що працювало. Дуже дякую!
JP Lew

crossOriginОпція jQuery, безумовно, не робить нічого для пом’якшення політики одного і того ж походження. Я б видалив цю відповідь, якби міг
Філ

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. Так чи інакше, дякую за відповідь.
Жолті

0

Я публікую це у випадку, якщо хтось стикається з тією ж проблемою, з якою я стикаюся зараз. У мене є тепловий принтер Zebra, оснащений сервером друку ZebraNet, який пропонує інтерфейс користувача на основі HTML для редагування кількох налаштувань, бачення поточного стану принтера тощо. Мені потрібно отримати статус принтера, який відображається на одній із тих html-сторінок, яку пропонує сервер ZebraNet і, наприклад, сповістити () повідомлення користувачеві у браузері. Це означає, що я повинен спочатку отримати цю сторінку HTML у Javascript. Незважаючи на те, що принтер знаходиться в локальній мережі ПК користувача, ця політика того ж джерелавсе ще твердо залишається на моєму шляху. Я спробував JSONP, але сервер повертає html, і я не знайшов способу змінити його функціональність (якби міг, я б уже встановив чарівний заголовок Access-control-enable-origin: *). Тому я вирішив написати невеликий додаток консолі в C #. Його потрібно запустити як Admin для належної роботи, інакше це тролі: 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

Щоб отримати зовнішній сайт форми даних, перейшовши за допомогою локального проксі-сервера, як це запропонував jherax, ви можете створити сторінку php, яка отримує вміст для вас із відповідної зовнішньої URL-адреси, а потім надіслати запит на отримання на цю сторінку 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

Вам потрібен проксі-сервер CORS, який передає ваш запит від вашого браузера до запитуваної послуги із відповідними заголовками CORS . Список таких служб знаходиться у фрагменті коду нижче. Ви також можете запустити наданий фрагмент коду, щоб побачити пінг для таких служб зі свого місцезнаходження.

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