597 votes

Comment puis-je envoyer un cross-domain requête POST via JavaScript?

Comment puis-je envoyer un cross-domain requête POST via JavaScript?

Remarque - il ne faut pas actualiser la page, et j'ai besoin de saisir et d'analyser la réponse par la suite.

Votre aide avec des exemples de code sera apprécié.

398voto

rynop Points 7818

Mise à jour: Avant de continuer, tout le monde doit lire et comprendre le html5rocks tutoriel sur la SCRO. Il est facile à comprendre et très clair.

Si vous contrôlez le serveur étant Affiché, il suffit de tirer parti de la "Cross-Origin Resource sharing standard" en-têtes de réponse sur le serveur. Cette réponse est discuté dans d'autres réponses dans ce fil, mais pas très clairement, à mon avis.

En bref voici comment vous accomplir la croix de domaine POSTE de from.com/1.html pour to.com/postHere.php (à l'aide de PHP par exemple). Remarque: vous ne devez définir Access-Control-Allow-Origin NON OPTIONS des demandes - cet exemple définit toujours tous les en-têtes pour un petit extrait de code.

  1. Dans postHere.php le programme d'installation suivants:

    switch ($_SERVER['HTTP_ORIGIN']) {
        case 'http://from.com': case 'https://from.com':
        header('Access-Control-Allow-Origin: '.$_SERVER['HTTP_ORIGIN']);
        header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');
        header('Access-Control-Max-Age: 1000');
        header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
        break;
    }
    

    Cela permet à votre script pour faire des croix domaine POST, GET et OPTIONS. Cela deviendra clair que vous continuez à lire...

  2. Le programme d'installation de votre croix de domaine POST JS (jQuery exemple):

    $.ajax({
        type: 'POST',
        url: 'https://to.com/postHere.php',
        crossDomain: true,
        data: '{"some":"json"}',
        dataType: 'json',
        success: function(responseData, textStatus, jqXHR) {
            var value = responseData.someKey;
        },
        error: function (responseData, textStatus, errorThrown) {
            alert('POST failed.');
        }
    });
    

Lorsque vous ne les POSTER dans l'étape 2, votre navigateur envoie une "OPTIONS" méthode pour le serveur. C'est un "sniff" par le navigateur pour voir si le serveur est cool avec vous publier des messages. Le serveur répond avec un "Access-Control-Allow-Origin" qui dit au navigateur que son OK pour POST|GET|ORIGINE si la demande provient de "http://from.com" ou "https://from.com". Étant donné que le serveur est OK avec elle, le navigateur va faire une 2e demande (cette fois un POST). Il est de bonne pratique de votre client défini le type de contenu qu'il est de l'envoi, - de sorte que vous aurez besoin pour permettre.

MDN a une grande écriture-up sur HTTP de contrôle d'accès, qui va dans le détail de la façon dont l'ensemble des flux de travaux. Selon leurs docs, il doit "travailler dans les navigateurs qui supportent le cross-site XMLHttpRequest". C'est un peu trompeur, cependant, je PENSE que seuls les navigateurs modernes permettent croix domaine de POSTE. J'ai seulement vérifié cela fonctionne avec safari,chrome,FF 3.6.

Gardez à l'esprit les points suivants si vous faites cela:

  1. Votre serveur va avoir à gérer 2 demandes par opération
  2. Vous aurez à réfléchir sur les implications de sécurité. Attention, avant de faire quelque chose comme " Access-Control-Allow-Origin: *'
  3. Cela ne marchera pas sur les navigateurs mobiles. Dans mon expérience, ils ne permettent pas de croix domaine de POSTE. J'ai testé android, iPad, iPhone
  4. Il y a un assez gros bug dans FF < 3.6 où si le serveur renvoie une valeur non 400 code de réponse ET il n'y est une réponse du corps (les erreurs de validation par exemple), FF 3.6 l'habitude d'obtenir le corps de la réponse. C'est une énorme douleur dans le cul, puisque vous ne pouvez pas utiliser de REPOS bien pratiques. Voir le bug ici (son déposée en vertu de jQuery, mais je pense que ses un FF bug semble être fixé dans FF4).
  5. Retournez toujours les en-têtes ci-dessus, et pas seulement sur OPTION des demandes. FF besoins dans la réponse de la POSTE.

124voto

Dan Fabulich Points 6143

Si vous contrôlez le serveur distant, vous devriez probablement utiliser la SCRO, comme décrit dans le haut de réponse sur cette question; il est pris en charge dans IE8 et en haut, et toutes les dernières versions de FF, GC, et Safari.

Mais si vous n'avez pas de contrôle sur le serveur distant, ou si vous avez à l'appui de IE7, vous voudrez probablement utiliser une iframe de la technique.

  1. Créer un iframe avec un nom unique. (iframes utiliser un espace de noms global pour l'ensemble du navigateur, afin de choisir un nom qu'aucun autre site.)
  2. Construire un formulaire avec des entrées, le ciblage de l'iframe.
  3. Soumettre le formulaire.

Voici un exemple de code; je l'ai testé sur IE6, IE7, IE8, IE9, FF4, GC11, S5.

function crossDomainPost() {
  // Add the iframe with a unique name
  var iframe = document.createElement("iframe");
  var uniqueString = "CHANGE_THIS_TO_SOME_UNIQUE_STRING";
  document.body.appendChild(iframe);
  iframe.style.display = "none";
  iframe.contentWindow.name = uniqueString;

  // construct a form with hidden inputs, targeting the iframe
  var form = document.createElement("form");
  form.target = uniqueString;
  form.action = "http://INSERT_YOUR_URL_HERE";
  form.method = "POST";

  // repeat for each parameter
  var input = document.createElement("input");
  input.type = "hidden";
  input.name = "INSERT_YOUR_PARAMETER_NAME_HERE";
  input.value = "INSERT_YOUR_PARAMETER_VALUE_HERE";
  form.appendChild(input);

  document.body.appendChild(form);
  form.submit();
}

Méfiez-vous! Vous ne serez pas en mesure de lire directement la réponse de la POSTE, depuis l'iframe existe sur un domaine distinct. Les Frames ne sont pas autorisés à communiquer les uns avec les autres à partir de différents domaines; c'est la même politique d'origine.

Si vous contrôlez le serveur distant, mais vous ne pouvez pas utiliser la SCRO pour une raison quelconque, il ya des façons de contourner la politique de " même origine, par exemple en utilisant window.postMessage et/ou l'un des un certain nombre de bibliothèques permettant d'envoyer de la croix-domaine de la croix-cadre des messages dans les anciens navigateurs:

Si vous n'avez pas de contrôle sur le serveur distant, vous ne pouvez pas lire la réponse de la POSTE, période. Il serait la cause de problèmes de sécurité autrement.

49voto

Lou Franco Points 48823
  1. Créer un iFrame,
  2. mettre un formulaire avec Caché entrées,
  3. définir l'action du formulaire à l'URL,
  4. Ajouter de l'iframe de document
  5. soumettre le formulaire

Pseudocode

 var ifr = document.createElement('iframe');
 var frm = document.createElement('form');
 frm.setAttribute("action", "yoururl");
 frm.setAttribute("method", "post");

 // create hidden inputs, add them
 // not shown, but similar (create, setAttribute, appendChild)

 ifr.appendChild(frm);
 document.body.appendChild(ifr);
 frm.submit();

Vous voulez probablement le style de l'iframe, pour être caché et en position absolue. Pas sûr de la croix de publication au site sera autorisé par le navigateur, mais si oui, c'est la façon de le faire.

16voto

Robb Lovell Points 139

Si vous avez accès à tous les serveurs impliqués, placez le code suivant dans l'en-tête de la réponse pour la page demandée dans l'autre domaine:

PHP:

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

Par exemple, dans de Drupal xmlrpc.php code vous voulez faire cela:

function xmlrpc_server_output($xml) {
    $xml = '<?xml version="1.0"?>'."\n". $xml;
    header('Connection: close');
    header('Content-Length: '. strlen($xml));
    header('Access-Control-Allow-Origin: *');
    header('Content-Type: application/x-www-form-urlencoded');
    header('Date: '. date('r'));
    // $xml = str_replace("\n", " ", $xml); 

    echo $xml;
    exit;
}

C'est probablement ce qui crée un problème de sécurité, et vous devriez vous assurer que vous prenez les mesures appropriées pour vérifier la demande.

9voto

ndeuma Points 386

Vérifier l' post_method fonction dans http://taiyolab.com/mbtweet/scripts/twitterapi_call.js - un bon exemple pour l'iframe méthode décrite ci-dessus.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X