Ładowanie punktu końcowego międzydomenowego za pomocą AJAX

132

Próbuję załadować stronę HTML międzydomenową przy użyciu technologii AJAX, ale nie mogę uzyskać odpowiedzi, chyba że typ danych to „jsonp”. Jednak używając jsonp, przeglądarka oczekuje typu MIME skryptu, ale odbiera „text / html”.

Mój kod do żądania to:

$.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 );
});

Czy istnieje sposób uniknięcia używania jsonp w żądaniu? Próbowałem już użyć parametru crossDomain, ale to nie zadziałało.

Jeśli nie, to czy istnieje sposób na otrzymanie zawartości html w jsonp? Obecnie konsola mówi „nieoczekiwany <” w odpowiedzi jsonp.

ksonorage
źródło
1
Rozwiązałem problem, tworząc proxy.php, jak wyjaśniono tutaj scode7.blogspot.com/2019/11/ ...
CodeDezk
Dzięki CodeDezk, utworzyłem własny serwer proxy PHP dla żądań AJAX międzydomenowych następujących po Twoim łączu. To było super łatwe.
GTS Joe

Odpowiedzi:

236

jQuery Ajax Notes

  • Ze względu na ograniczenia bezpieczeństwa przeglądarki większość żądań Ajax podlega tym samym zasadom pochodzenia ; żądanie nie może pomyślnie pobrać danych z innej domeny, subdomeny, portu lub protokołu.
  • Żądania skryptów i JSONP nie podlegają tym samym ograniczeniom zasad pochodzenia.

Istnieje kilka sposobów na pokonanie bariery międzydomenowej :

Istnieje kilka wtyczek, które pomagają w przypadku żądań między domenami :

Heads-up!

Najlepszym sposobem rozwiązania tego problemu jest utworzenie własnego serwera proxy na zapleczu, tak aby serwer proxy wskazywał usługi w innych domenach, ponieważ w zapleczu nie istnieje takie samo ograniczenie zasad pochodzenia . Ale jeśli nie możesz tego zrobić na zapleczu, zwróć uwagę na następujące wskazówki.


Ostrzeżenie!

Korzystanie z serwerów proxy innych firm nie jest bezpieczną praktyką, ponieważ mogą one śledzić Twoje dane, dzięki czemu można ich używać z informacjami publicznymi, ale nigdy z danymi prywatnymi.


Poniższe przykłady kodu używają jQuery.get () i jQuery.getJSON () , oba są skrótami metod jQuery.ajax ()


CORS Anywhere

CORS Anywhere to serwer proxy node.js, który dodaje nagłówki CORS do żądania, które jest przesyłane przez serwer proxy .
Aby skorzystać z interfejsu API, wystarczy poprzedzić adres URL adresem URL interfejsu API. (Obsługuje https : zobacz repozytorium github )

Jeśli chcesz automatycznie włączać żądania między domenami w razie potrzeby, użyj następującego fragmentu kodu:

$.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);
});


Niezależnie od pochodzenia

Niezależnie od pochodzenia jest to międzydomenowy dostęp jsonp . Jest to alternatywa typu open source dla anyorigin.com .

Aby pobrać dane z google.com, możesz użyć tego fragmentu:

// 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);
});


Pełnomocnik CORS

CORS Proxy to prosty serwer proxy node.js, który umożliwia wysyłanie żądań CORS do dowolnej witryny internetowej. Umożliwia kodowi javascript w Twojej witrynie dostęp do zasobów w innych domenach, które normalnie byłyby blokowane ze względu na zasady tego samego pochodzenia.

Jak to działa? CORS Proxy korzysta z współdzielenia zasobów między źródłami, które jest funkcją dodaną wraz z HTML 5. Serwery mogą określić, że chcą, aby przeglądarki zezwalały innym witrynom na żądanie zasobów, które hostują. CORS Proxy to po prostu serwer proxy HTTP, który dodaje nagłówek do odpowiedzi mówiący „każdy może o to poprosić”.

To kolejny sposób na osiągnięcie celu (patrz www.corsproxy.com ). Wszystko, co musisz zrobić, to usunąć http: // i www. z adresu URL, który ma być proxy, i wstaw go na początkuwww.corsproxy.com/

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


Przeglądarka proxy CORS

Niedawno znalazłem ten, który obejmuje różne zorientowane na bezpieczeństwo narzędzia do zdalnego udostępniania Cross Origin. Ale jest to czarna skrzynka z Flash'em jako zapleczem.

Możesz zobaczyć to w akcji tutaj: Przeglądarka proxy CORS
Pobierz kod źródłowy na GitHub: koto / cors-proxy-browser

jherax
źródło
4
Możesz także wdrożyć własną wersję WhatersOrigin.org
EpicVoyage
1
Obrazy, CSS i zewnętrzny javascript można odwoływać się z innego źródła, dlatego w odpowiedzi możesz przejść przez ciąg HTML i zastąpić src zasobów zewnętrznych
jherax
1
cześć jherax Użyłem anyorigin, aby uzyskać stronę html (tylko sposób działał dla mnie, użyłem yql, google itp.), Ale inne niż angielskie znaki są dziwne. próbował zakodować dane.contents, ale nie pomogło
user217648
1
Witaj @Miru, jak mówi tytuł: „Ładowanie strony html między domenami za pomocą jQuery AJAX”, odpowiedziałem na tytuł, podając kilka przykładów użycia proxy do wykonywania żądań międzydomenowych. Ponadto, w odpowiedzi na sformułowanie pytania, podałem kilka linków do wysyłania zapytań międzydomenowych przy użyciu JSONP z YQL. Zapraszam do zapoznania się z linkami, są bardzo przydatne.
jherax
1
Skończyło się na użyciu metody CORS Anywhere z $.ajaxPrefilteri działało świetnie. Wielkie dzięki!
Joshua Pinter
24

Możesz użyć Ajax-cross-origin i wtyczki jQuery. Dzięki tej wtyczce korzystasz z jQuery.ajax()wielu domen. W tym celu korzysta z usług Google:

Wtyczka AJAX Cross Origin używa Google Apps Script jako proxy pobierającego jSON, gdy jSONP nie jest zaimplementowany. Gdy ustawisz opcję crossOrigin na wartość true, wtyczka zamieni oryginalny adres URL na adres Google Apps Script i wyśle ​​go jako parametr zakodowanego adresu URL. Skrypt Aplikacji Google korzysta z zasobów serwerów Google, aby uzyskać zdalne dane i zwrócić je z powrotem do klienta w postaci JSONP.

Jest bardzo prosty w użyciu:

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

Możesz przeczytać więcej tutaj: http://www.ajax-cross-origin.com/

Ninioe
źródło
22
Jeśli o mnie chodzi, ta wtyczka nigdy nie działała. To nic nie robi w Chrome.
Michael,
Jak mogę uwierzytelnić się na serwerze?
sttaq
działa świetnie! Interfejs API, którego używam, nie obsługuje formatu JSONP ani CORS, więc jest to jedyna rzecz, która zadziałała. Wielkie dzięki!
JP Lew
crossOriginOpcja jQuery z pewnością nie robi nic, aby złagodzić zasady tego samego pochodzenia. Skasowałbym tę odpowiedź, gdybym mógł
Phil
13

Jeśli witryna zewnętrzna nie obsługuje formatu JSONP lub CORS, jedyną opcją jest użycie serwera proxy.

Zbuduj skrypt na serwerze, który żąda tej zawartości, a następnie użyj jQuery ajax, aby uruchomić skrypt na serwerze.

Kevin B.
źródło
5

Po prostu umieść to w nagłówku swojej strony PHP i będzie działać bez API:

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

lub

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

lub

$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");
}
studio-klik
źródło
Zastanawiam się, skąd $_SERVER['HTTP_ORIGIN']to pochodzi. Nie mogłem go znaleźć w dokumentacji PHP ani nigdzie indziej.
Zsolti
Hmm, wygląda na to, że jest wypełniony tylko żądaniami AJAX. W każdym razie dzięki za odpowiedź.
Zsolti
0

Publikuję to na wypadek, gdyby ktoś napotkał ten sam problem, z którym mam teraz do czynienia. Mam drukarkę termiczną Zebra, wyposażoną w serwer druku ZebraNet, który oferuje interfejs użytkownika oparty na języku HTML do edycji wielu ustawień, sprawdzania aktualnego stanu drukarki itp. Potrzebuję uzyskać stan drukarki, który jest wyświetlany na jednej z tych stron html, oferowanej przez serwer ZebraNet i na przykład alert (), wiadomość dla użytkownika w przeglądarce. Oznacza to, że najpierw muszę pobrać tę stronę HTML w Javascript. Chociaż drukarka znajduje się w sieci LAN komputera użytkownika, obowiązuje ta sama zasada pochodzenianadal mocno mi przeszkadza. Próbowałem JSONP, ale serwer zwraca html i nie znalazłem sposobu na modyfikację jego funkcjonalności (gdybym mógł, ustawiłbym już magiczny nagłówek Access-control-allow-origin: *). Postanowiłem więc napisać małą aplikację konsolową w C #. Musi być uruchomiony jako Admin, aby działał poprawnie, w przeciwnym razie trolluje: D wyjątek. Oto kod:

// 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();

Użytkownik musi tylko uruchomić tę aplikację konsoli jako administrator. Wiem, że jest to zbyt ... frustrujące i skomplikowane, ale jest to swego rodzaju obejście problemu z zasadami domeny, na wypadek gdybyś nie mógł w żaden sposób zmodyfikować serwera.

edycja: z js wykonuję proste wywołanie 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);
                }
            });

Kod HTML żądanej strony jest zwracany i przechowywany w zmiennej data .

user2177283
źródło
0

Aby uzyskać dane z zewnętrznej witryny, przekazując je za pomocą lokalnego serwera proxy, zgodnie z sugestią jherax, możesz utworzyć stronę php, która pobiera zawartość dla Ciebie z odpowiedniego zewnętrznego adresu URL, a następnie wysłać żądanie pobierania do tej strony php.

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

jako proxy php możesz użyć https://github.com/cowboy/php-simple-proxy

Nitigya Sharma
źródło
0

Twój URLobecnie nie działa, ale kod można zaktualizować za pomocą tego działającego rozwiązania:

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>

350D
źródło
-2

Potrzebujesz serwera proxy CORS, który przekazuje żądanie z przeglądarki do żądanej usługi z odpowiednimi nagłówkami CORS . Lista takich usług znajduje się we fragmencie kodu poniżej. Możesz również uruchomić udostępniony fragment kodu, aby zobaczyć ping do takich usług z Twojej lokalizacji.

$('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>

galeksandrp
źródło
11
To w żaden sposób nie odpowiada na pytanie.
0xc0de
@ 0xc0de w końcu napisałem odpowiedź.
galeksandrp
-7

Domyśliłam się. Zamiast tego użyłem tego.

$('.div_class').load('http://en.wikipedia.org/wiki/Cross-origin_resource_sharing #toctitle');
user3279865
źródło
Kod, którego tam użyłeś, jest nieistotny. Liczy się nagłówki CORS po stronie serwera.
Quentin