Chargement du point de terminaison inter-domaines avec AJAX

131

J'essaye de charger une page HTML inter-domaines en utilisant AJAX mais à moins que le dataType soit "jsonp" je ne peux pas obtenir de réponse. Cependant, en utilisant jsonp, le navigateur attend un type de script mime mais reçoit "text / html".

Mon code pour la demande est:

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

Existe-t-il un moyen d'éviter d'utiliser jsonp pour la requête? J'ai déjà essayé d'utiliser le paramètre crossDomain mais cela n'a pas fonctionné.

Sinon, y a-t-il un moyen de recevoir le contenu html dans jsonp? Actuellement, la console dit "inattendu <" dans la réponse jsonp.

xonorage
la source
J'ai résolu le problème en créant un proxy.php comme expliqué ici scode7.blogspot.com/2019/11
...

Réponses:

235

Notes jQuery Ajax

  • En raison des restrictions de sécurité du navigateur, la plupart des demandes Ajax sont soumises à la même politique d'origine ; la demande ne parvient pas à récupérer les données d'un autre domaine, sous-domaine, port ou protocole.
  • Les requêtes de script et JSONP ne sont pas soumises aux mêmes restrictions de politique d'origine.

Il y a des façons de surmonter la interdomaine barrière:

Il existe des plugins qui aident avec les requêtes inter-domaines :

La tête haute!

La meilleure façon de surmonter ce problème est de créer votre propre proxy dans le back-end, de sorte que votre proxy pointe vers les services dans d'autres domaines, car dans le back-end n'existe pas la même restriction de politique d'origine . Mais si vous ne pouvez pas faire cela dans le back-end, faites attention aux conseils suivants.


Avertissement!

L'utilisation de proxys tiers n'est pas une pratique sécurisée, car ils peuvent garder une trace de vos données, afin qu'elles puissent être utilisées avec des informations publiques, mais jamais avec des données privées.


Les exemples de code ci-dessous utilisent jQuery.get () et jQuery.getJSON () , les deux sont des méthodes abrégées de jQuery.ajax ()


CORS n'importe où

CORS Anywhere est un proxy node.js qui ajoute des en-têtes CORS à la requête mandatée.
Pour utiliser l'API, préfixez simplement l'URL avec l'URL de l'API. (Prend en charge https : voir le référentiel github )

Si vous souhaitez activer automatiquement les requêtes inter-domaines en cas de besoin, utilisez l'extrait de code suivant:

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


Quelle que soit l'origine

Quelle que soit l'origine est un accès jsonp interdomaine . Ceci est une alternative open source à anyorigin.com .

Pour récupérer les données de google.com, vous pouvez utiliser cet extrait:

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


Proxy CORS

CORS Proxy est un simple proxy node.js pour activer la requête CORS pour n'importe quel site Web. Il permet au code javascript sur votre site d'accéder à des ressources sur d'autres domaines qui seraient normalement bloqués en raison de la politique de même origine.

Comment ça marche? CORS Proxy tire parti du partage de ressources cross-origin, qui est une fonctionnalité qui a été ajoutée avec HTML 5. Les serveurs peuvent spécifier qu'ils souhaitent que les navigateurs autorisent d'autres sites Web à demander les ressources qu'ils hébergent. CORS Proxy est simplement un proxy HTTP qui ajoute un en-tête aux réponses disant "n'importe qui peut demander ceci".

C'est une autre façon d'atteindre l'objectif (voir www.corsproxy.com ). Tout ce que vous avez à faire est de déshabiller http: // et www. à partir de l'URL faisant l'objet d'un proxy, et ajoutez l'URL avecwww.corsproxy.com/

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


Navigateur proxy CORS

Récemment, j'ai trouvé celui-ci, il implique divers utilitaires de partage à distance Cross Origin orientés sécurité. Mais c'est une boîte noire avec Flash comme backend.

Vous pouvez le voir en action ici: Navigateur proxy CORS
Obtenez le code source sur GitHub: koto / cors-proxy-browser

jherax
la source
4
Vous pouvez également déployer votre propre version de WhateverOrigin.org (ou porter le code pour votre propre usage) à partir d'ici: github.com/ripper234/Wwhat-Origin
EpicVoyage
1
Les images, le CSS et le javascript externe peuvent être référencés à partir d'une autre origine, ainsi, dans la réponse, vous pouvez parcourir la chaîne HTML et remplacer le src des ressources externes
jherax
1
salut jherax J'ai utilisé n'importe quelle origine pour obtenir une page html (la seule façon a fonctionné pour moi, utilisé yql, google, etc.) mais les caractères non anglais sont étranges. essayé d'encoder data.contents mais pas aidé
user217648
1
Bonjour @Miru, comme le dit le titre: "Chargement d'une page html interdomaine avec jQuery AJAX", j'ai répondu au titre en fournissant quelques exemples utilisant un proxy pour effectuer des requêtes interdomaines. De plus, en réponse au libellé de la question, j'ai fourni des liens pour effectuer des requêtes inter-domaines en utilisant JSONP avec YQL. Je vous invite à lire les liens, ils sont très utiles.
jherax
1
J'ai fini par utiliser la méthode CORS Anywhere avec $.ajaxPrefilteret cela a très bien fonctionné. Merci beaucoup!
Joshua Pinter
24

Vous pouvez utiliser Ajax-cross-origin un plugin jQuery. Avec ce plugin, vous utilisez jQuery.ajax()cross domain. Il utilise les services de Google pour y parvenir:

Le plug-in AJAX Cross Origin utilise Google Apps Script comme getter proxy jSON où jSONP n'est pas implémenté. Lorsque vous définissez l'option crossOrigin sur true, le plug-in remplace l'URL d'origine par l'adresse de script Google Apps et l'envoie en tant que paramètre d'URL encodée. Le script Google Apps utilise les ressources des serveurs Google pour obtenir les données distantes et les renvoyer au client au format JSONP.

C'est très simple à utiliser:

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

Vous pouvez en savoir plus ici: http://www.ajax-cross-origin.com/

Ninioe
la source
22
En ce qui me concerne, ce plugin n'a jamais fonctionné. Cela ne fait rien sur Chrome.
Michael
Comment puis-je m'authentifier auprès du serveur?
sttaq
fonctionne très bien! L'API que j'utilise ne prend en charge ni JSONP ni CORS, c'est donc la seule chose qui a fonctionné. Merci beaucoup!
JP Lew
L' crossOriginoption de jQuery ne fait certainement rien pour atténuer les politiques de même origine. Je supprimerais cette réponse si je pouvais
Phil
13

Si le site externe ne prend pas en charge JSONP ou CORS, votre seule option est d'utiliser un proxy.

Créez un script sur votre serveur qui demande ce contenu, puis utilisez jQuery ajax pour lancer le script sur votre serveur.

Kevin B
la source
5

Mettez simplement ceci dans l'en-tête de votre page PHP et cela ne fonctionnera pas sans API:

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

ou

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

ou

$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
la source
Je me demande d'où $_SERVER['HTTP_ORIGIN']vient. Je n'ai pas pu le trouver dans la documentation PHP ou ailleurs.
Zsolti
Hmm, il semble qu'il ne soit rempli que de requêtes AJAX. Quoi qu'il en soit, merci pour la réponse.
Zsolti
0

Je poste ceci au cas où quelqu'un serait confronté au même problème que celui auquel je suis confronté actuellement. J'ai une imprimante thermique Zebra, équipée du serveur d'impression ZebraNet, qui offre une interface utilisateur basée sur HTML pour modifier plusieurs paramètres, voir l'état actuel de l'imprimante, etc. J'ai besoin d'obtenir l'état de l'imprimante, qui est affiché dans l'une de ces pages html, proposées par le serveur ZebraNet et, par exemple, alert () un message à l'utilisateur dans le navigateur. Cela signifie que je dois d'abord obtenir cette page html en Javascript. Bien que l'imprimante se trouve dans le réseau local du PC de l'utilisateur, cette même politique d'originereste fermement sur mon chemin. J'ai essayé JSONP, mais le serveur renvoie html et je n'ai pas trouvé de moyen de modifier ses fonctionnalités (si je pouvais, j'aurais déjà défini l'en-tête magique Access-control-allow-origin: *). J'ai donc décidé d'écrire une petite application console en C #. Il doit être exécuté en tant qu'administrateur pour fonctionner correctement, sinon il trolls: D une exception. Voici un code:

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

Tout ce que l'utilisateur doit faire est d'exécuter cette application de console en tant qu'administrateur. Je sais que c'est trop ... frustrant et compliqué, mais c'est en quelque sorte une solution de contournement au problème de politique de domaine au cas où vous ne pourriez pas modifier le serveur de quelque manière que ce soit.

edit: depuis js je fais un simple appel 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);
                }
            });

Le html de la page demandée est retourné et stocké dans la variable de données .

user2177283
la source
0

Pour obtenir le site externe du formulaire de données en utilisant un proxy local comme suggéré par jherax, vous pouvez créer une page php qui récupère le contenu pour vous à partir de l'url externe respective et ensuite envoyer une demande d'obtention à cette page php.

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

en tant que proxy php, vous pouvez utiliser https://github.com/cowboy/php-simple-proxy

Nitigya Sharma
la source
0

Votre URLne fonctionne pas ces jours-ci, mais votre code peut être mis à jour avec cette solution fonctionnelle:

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
la source
-2

Vous avez besoin d'un proxy CORS qui transmet par proxy votre demande de votre navigateur au service demandé avec les en- têtes CORS appropriés . La liste de ces services se trouve dans l'extrait de code ci-dessous. Vous pouvez également exécuter l'extrait de code fourni pour voir le ping vers ces services à partir de votre emplacement.

$('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
la source
11
Cela ne répond en aucun cas à la question.
0xc0de
@ 0xc0de j'ai enfin écrit la réponse.
galeksandrp
-7

Deviner. Utilisé ceci à la place.

$('.div_class').load('http://en.wikipedia.org/wiki/Cross-origin_resource_sharing #toctitle');
user3279865
la source
Le code que vous avez utilisé là-bas n'est pas pertinent. Ce qui compte, ce sont les en-têtes CORS côté serveur.
Quentin