web-dev-qa-db-fra.com

jQuery AJAX domaine croisé

Voici deux pages, test.php et testserver.php.

test.php

<script src="scripts/jq.js" type="text/javascript"></script>
<script>
    $(function() {
        $.ajax({url:"testserver.php",
            success:function() {
                alert("Success");
            },
            error:function() {
                alert("Error");
            },
            dataType:"json",
            type:"get"
        }
    )})
</script>

testserver.php

<?php
$arr = array("element1",
             "element2",
             array("element31","element32"));
$arr['name'] = "response";
echo json_encode($arr);
?>

Maintenant, mon problème: lorsque ces deux fichiers sont sur le même serveur (localhost ou web server), cela fonctionne et alert("Success") est appelé; S'il se trouve sur des serveurs différents, ce qui signifie testserver.php sur le serveur Web et test.php sur localhost, cela ne fonctionne pas et alert("Error") est en cours d'exécution. Même si l’URL dans ajax est modifié en http://domain.com/path/to/file/testserver.php

461
Firose Hussain

Utilisez JSONP .

jQuery:

$.ajax({
     url:"testserver.php",
     dataType: 'jsonp', // Notice! JSONP <-- P (lowercase)
     success:function(json){
         // do stuff with json (in this case an array)
         alert("Success");
     },
     error:function(){
         alert("Error");
     }      
});

PHP:

<?php
$arr = array("element1","element2",array("element31","element32"));
$arr['name'] = "response";
echo $_GET['callback']."(".json_encode($arr).");";
?>

L'écho peut être faux, cela fait longtemps que je n'ai pas utilisé php. Dans tous les cas, vous devez sortir callbackName('jsonString') notez les guillemets. jQuery transmettra son propre nom de rappel, vous devez donc l'obtenir des paramètres GET.

Et comme l'a écrit Stefan Kendall, $. GetJSON () est une méthode abrégée, mais vous devez ensuite ajouter 'callback=?' à l'URL en tant que paramètre GET (oui, la valeur est?, JQuery le remplace avec sa propre méthode de rappel générée).

407
BGerrissen

JSONP est une bonne option, mais il existe un moyen plus simple. Vous pouvez simplement définir l'en-tête Access-Control-Allow-Origin sur votre serveur. Le régler sur * acceptera les demandes interdomaines AJAX de n'importe quel domaine. ( https://developer.mozilla.org/en/http_access_control )

La méthode pour ce faire varie bien sûr d’une langue à l’autre. La voici dans Rails:

class HelloController < ApplicationController
  def say_hello
    headers['Access-Control-Allow-Origin'] = "*"
    render text: "hello!"
  end
end

Dans cet exemple, l'action say_hello acceptera les demandes AJAX de n'importe quel domaine et renverra une réponse "bonjour!".

Voici un exemple d'en-têtes qu'il pourrait renvoyer:

HTTP/1.1 200 OK 
Access-Control-Allow-Origin: *
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Type: text/html; charset=utf-8
X-Ua-Compatible: IE=Edge
Etag: "c4ca4238a0b923820dcc509a6f75849b"
X-Runtime: 0.913606
Content-Length: 6
Server: WEBrick/1.3.1 (Ruby/1.9.2/2011-07-09)
Date: Thu, 01 Mar 2012 20:44:28 GMT
Connection: Keep-Alive

Aussi simple que cela puisse paraître, il présente certaines limitations du navigateur. Voir http://caniuse.com/#feat=cors .

200
joshuarh

Vous pouvez contrôler ceci via l'en-tête HTTP en ajoutant Access-Control-Allow-Origin. Si vous le définissez sur *, les requêtes interdomaines AJAX de tous les domaines seront acceptées.

En utilisant PHP c'est très simple, ajoutez simplement la ligne suivante dans le script auquel vous voulez avoir accès en dehors de votre domaine:

header("Access-Control-Allow-Origin: *");

N'oubliez pas d'activer le module mod_headers dans httpd.conf.

30
Adorjan Princz

Vous devez jeter un oeil sur politique de même origine :

En informatique, la même politique d'origine est un concept de sécurité important pour un certain nombre de langages de programmation côté navigateur, tels que JavaScript. La stratégie permet aux scripts s'exécutant sur des pages provenant du même site d'accéder aux méthodes et aux propriétés des autres sans restrictions spécifiques, mais empêche l'accès à la plupart des méthodes et propriétés sur plusieurs pages de différents sites.

Pour que vous puissiez obtenir des données, il faut que:

Même protocole et hôte

Vous devez implémenter JSONP pour contourner le problème.

19
Sarfraz

Je devais charger la page Web à partir du disque local "fichier: /// C: /test/htmlpage.html", appeler "http: //localhost/getxml.php" url et le faire dans les navigateurs IE8 + et Firefox12 +, utiliser jQuery v1 .7.2 lib pour minimiser le code passe-partout. Après avoir lu des dizaines d'articles, j'ai finalement compris. Voici mon résumé.

  • le script de serveur (.php, .jsp, ...) doit renvoyer l'en-tête de réponse http Access-Control-Allow-Origin: *
  • avant d'utiliser jQuery ajax, définissez cet indicateur en javascript: jQuery.support.cors = true;
  • vous pouvez définir l'indicateur une fois ou à chaque fois avant d'utiliser la fonction ajax de jQuery
  • je peux maintenant lire le document .xml dans IE et Firefox. Autres navigateurs que je n'ai pas testés.
  • le document de réponse peut être plain/text, xml, json ou autre

Voici un exemple d'appel jQuery ajax avec quelques sysouts de débogage.

jQuery.support.cors = true;
$.ajax({
    url: "http://localhost/getxml.php",
    data: { "id":"doc1", "rows":"100" },
    type: "GET",
    timeout: 30000,
    dataType: "text", // "xml", "json"
    success: function(data) {
        // show text reply as-is (debug)
        alert(data);

        // show xml field values (debug)
        //alert( $(data).find("title").text() );

        // loop JSON array (debug)
        //var str="";
        //$.each(data.items, function(i,item) {
        //  str += item.title + "\n";
        //});
        //alert(str);
    },
    error: function(jqXHR, textStatus, ex) {
        alert(textStatus + "," + ex + "," + jqXHR.responseText);
    }
});
16
Whome

Il est vrai que la règle same-Origin empêche JavaScript de faire des requêtes sur plusieurs domaines, mais la spécification CORS autorise uniquement le type d'accès à l'API que vous recherchez et est prise en charge par le lot actuel de principaux navigateurs.

Découvrez comment activer le partage de ressources inter-origines pour le client et le serveur:

http://enable-cors.org/

"Le partage de ressources inter-origines (CORS) est une spécification qui permet un accès véritablement ouvert au-delà des limites du domaine. Si vous diffusez du contenu public, envisagez d'utiliser CORS pour l'ouvrir pour un accès universel par JavaScript/navigateur."

10
Jason

C'est possible, mais vous devez utiliser JSONP, pas JSON. Le lien de Stefan vous a dirigé dans la bonne direction. La jQuery AJAX page contient plus d'informations sur JSONP.

Remy Sharp a un exemple détaillé en utilisant PHP .

9
Paul Schreiber

J'utilise le serveur Apache, donc j'ai utilisé le module mod_proxy. Activer les modules:

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

Puis ajouter:

ProxyPass /your-proxy-url/ http://service-url:serviceport/

Enfin, passez proxy-url à votre script.

9
zenio

La sécurité du navigateur empêche de passer un appel ajax d’une page hébergée sur un domaine à une page hébergée sur un autre domaine; c'est ce qu'on appelle le " politique de même origine ".

8
Jacob Mattison

Il existe peu d'exemples d'utilisation de JSONP qui incluent la gestion des erreurs.

Cependant, veuillez noter que l'erreur-événement n'est pas déclenché lors de l'utilisation de JSONP! Voir: http://api.jquery.com/jQuery.ajax/ ou demande jQuery ajax utilisant l'erreur jsonp

5
BillyTom

À partir de la documentation Jquery ( lien ):

  • 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 peut pas récupérer les données d'un domaine, sous-domaine ou protocole différent.

  • Les requêtes de script et JSONP ne sont pas soumises aux mêmes restrictions de stratégie d'origine.

Je suppose donc que vous devez utiliser jsonp pour la requête. Mais je n'ai pas essayé moi-même.

4
William Clemens

Je sais 3 façons de résoudre votre problème:

  1. Tout d'abord, si vous avez accès aux deux domaines, vous pouvez autoriser l'accès à tous les autres domaines en utilisant:

    header("Access-Control-Allow-Origin: *");

    ou simplement un domaine en ajoutant le code ci-dessous au fichier .htaccess:

    <FilesMatch "\.(ttf|otf|eot|woff)$"> <IfModule mod_headers.c> SetEnvIf Origin "http(s)?://(www\.)?(google.com|staging.google.com|development.google.com|otherdomain.net|dev02.otherdomain.net)$" AccessControlAllowOrigin=$0 Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin </IfModule> </FilesMatch>

  2. vous pouvez avoir une demande ajax dans un fichier php sur votre serveur et gérer la demande dans un autre domaine en utilisant ce fichier php.

  3. vous pouvez utiliser jsonp, car il n'a pas besoin d'autorisation. Pour cela, vous pouvez lire la réponse de notre ami @BGerrissen.
1
Ali_Hr

cela fonctionne, tout ce dont vous avez besoin:

PHP:

header('Access-Control-Allow-Origin: http://www.example.com');
header("Access-Control-Allow-Credentials: true");
header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');

JS (jQuery ajax):

var getWBody = $.ajax({ cache: false,
        url: URL,
        dataType : 'json',
        type: 'GET',
        xhrFields: { withCredentials: true }
});
0

Pour Microsoft Azure, c'est légèrement différent.

Azure a un paramètre CORS spécial qui doit être défini. C'est essentiellement la même chose dans les coulisses, mais définir simplement l'en-tête que joshuarh mentionne ne fonctionnera pas. La documentation Azure pour l'activation inter-domaine peut être trouvée ici:

https://docs.Microsoft.com/en-us/Azure/app-service-api/app-service-api-cors-consume-javascript

Je me suis amusé avec cela pendant quelques heures avant de réaliser que ma plate-forme d’hébergement disposait de ce paramètre particulier.

0
Josh Schultz