602

JavaScript を介してクロスドメイン POST リクエストを送信するにはどうすればよいですか?

注 - ページを更新するべきではなく、後で応答を取得して解析する必要があります。

4

17 に答える 17

399

更新:続行する前に、全員がCORS に関するhtml5rocks チュートリアルを読んで理解する必要があります。わかりやすくてとてもわかりやすいです。

POST されているサーバーを制御する場合は、サーバーに応答ヘッダーを設定して、「クロスオリジン リソース共有標準」を利用するだけです。この回答は、このスレッドの他の回答で議論されていますが、私の意見ではあまり明確ではありません。

要するに、from.com/1.html から to.com/postHere.php へのクロスドメイン POST を実行する方法を次に示します (例として PHP を使用)。Access-Control-Allow-Origin注: NONリクエストに対してのみ設定する必要があります。OPTIONSこの例では、常に小さなコード スニペットのすべてのヘッダーを設定します。

  1. postHere.php で次のように設定します。

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

    これにより、スクリプトでクロスドメイン POST、GET、および OPTIONS を作成できます。これは読み進めていくうちに明らかになる...

  2. JS からクロスドメイン POST をセットアップします (jQuery の例):

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

ステップ 2 で POST を実行すると、ブラウザは「OPTIONS」メソッドをサーバーに送信します。これは、ブラウザによる「スニフ」であり、サーバーへの POST でサーバーがクールかどうかを確認します。サーバーは、リクエストが「 http://from.com」または「https://from.com 」から発信された場合、ブラウザに POST|GET|ORIGIN のOKを伝える「Access-Control-Allow-Origin」で応答します。サーバーは問題ないので、ブラウザーは 2 番目の要求 (今回は POST) を行います。送信するコンテンツ タイプをクライアントに設定させることをお勧めします。そのため、それも許可する必要があります。

MDN にはHTTP アクセス制御に関する優れた記事があり、フロー全体がどのように機能するかを詳しく説明しています。彼らのドキュメントによると、「クロスサイト XMLHttpRequest をサポートするブラウザーで動作する」はずです。ただし、これは少し誤解を招く可能性があります。クロス ドメイン POST を許可するのは最近のブラウザーだけだと思う​​からです。これが safari、chrome、FF 3.6 でのみ動作することを確認しました。

これを行う場合は、次の点に注意してください。

  1. サーバーは操作ごとに 2 つのリクエストを処理する必要があります
  2. セキュリティへの影響について考える必要があります。「Access-Control-Allow-Origin: *」のようなことを行う前に注意してください。
  3. これはモバイル ブラウザでは機能しません。私の経験では、クロスドメイン POST はまったく許可されていません。私はアンドロイド、iPad、iPhoneをテストしました
  4. FF < 3.6 にはかなり大きなバグがあり、サーバーが 400 以外の応答コードを返し、応答本文 (検証エラーなど) がある場合、FF 3.6 は応答本文を取得しません。優れた REST プラクティスを使用できないため、これは大きな苦痛です。ここでバグを参照してください(jQueryの下にファイルされていますが、私の推測ではFFのバグです-FF4で修正されているようです)。
  5. OPTION リクエストだけでなく、常に上記のヘッダーを返します。FF は、POST からの応答でそれを必要とします。
于 2011-09-30T01:34:23.913 に答える
124

リモートサーバーを制御する場合は、この回答で説明されているように、おそらく CORS を使用する必要があります。IE8 以降、および最近のすべてのバージョンの FF、GC、および Safari でサポートされています。(ただし、IE8 および 9 では、CORS はリクエストで Cookie を送信することを許可しません。)

したがって、リモート サーバーを制御しない場合、または IE7 をサポートする必要がある場合、または Cookie が必要で IE8/9 をサポートする必要がある場合は、おそらく iframe 手法を使用することをお勧めします。

  1. 一意の名前で iframe を作成します。(iframe はブラウザー全体でグローバルな名前空間を使用するため、他の Web サイトが使用しない名前を選択してください。)
  2. iframe をターゲットにして、非表示の入力を含むフォームを作成します。
  3. フォームを送信します。

サンプルコードは次のとおりです。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();
}

注意してください!iframe は別のドメインに存在するため、POST の応答を直接読み取ることはできません。フレームが異なるドメインから相互に通信することは許可されていません。これが同一生成元ポリシーです。

window.postMessageリモート サーバーを制御しているが、CORS を使用できない場合 (たとえば、IE8/IE9 を使用していて、Cookie を使用する必要があるため)、および/またはを使用するなど、同一生成元ポリシーを回避する方法があります。古いブラウザーでクロスドメイン クロスフレーム メッセージを送信できるようにする多くのライブラリの 1 つ:

リモートサーバーを制御しないと、POST の応答を読み取ることができません。そうしないと、セキュリティ上の問題が発生します。

于 2011-05-29T18:50:30.857 に答える
49
  1. iFrame を作成し、
  2. 隠し入力でフォームを入れて、
  3. フォームのアクションを URL に設定し、
  4. iframe をドキュメントに追加する
  5. フォームを送信する

疑似コード

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

おそらく、iframe を非表示にして絶対に配置するようにスタイルを設定する必要があります。ブラウザでクロスサイト投稿が許可されるかどうかはわかりませんが、許可されている場合は、これがその方法です。

于 2008-11-18T13:49:36.293 に答える
24

複雑にしないでおく:

  1. クロスドメイン POST:
    使用crossDomain: true,

  2. ページを更新しないでください:
    いいえ、サーバーが応答を返すときにsuccessまたはerror


スクリプト例:

$.ajax({
        type: "POST",
        url: "http://www.yoururl.com/",
        crossDomain: true,
        data: 'param1=value1&param2=value2',
        success: function (data) {
            // do something with server response data
        },
        error: function (err) {
            // handle your error logic here
        }
    });
于 2014-10-03T17:01:45.480 に答える
16

関係するすべてのサーバーにアクセスできる場合は、他のドメインで要求されているページの返信のヘッダーに次のように入力します。

PHP:

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

たとえば、Drupal の xmlrpc.php コードでは、次のようにします。

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

これはおそらくセキュリティ上の問題を引き起こすため、適切な手段を講じてリクエストを確認する必要があります。

于 2011-01-22T00:40:05.317 に答える
9

http://taiyolab.com/mbtweet/scripts/twitterapi_call.jspost_methodで関数を確認してください- 上記の iframe メソッドの良い例です。

于 2010-02-24T22:03:35.440 に答える
6
  1. 2つの非表示のiframeを作成します(cssスタイルに「display:none;」を追加します)。2番目のiframeが自分のドメイン上の何かを指すようにします。

  2. 非表示のフォームを作成し、そのメソッドをtarget =最初のiframeで「post」に設定し、オプションでenctypeを「multipart / form-data」に設定します(写真のようなマルチパートデータを送信したいので、POSTを実行したいと思います?)

  3. 準備ができたら、フォームsubmit()をPOSTにします。

  4. 他のドメインにIframeとのクロスドメイン通信を行うJavaScriptを返すことができれば(http://softwareas.com/cross-domain-communication-with-iframes)、運が良ければ、応答をキャプチャできます。同じように。

もちろん、サーバーをプロキシとして使用する場合は、これをすべて回避できます。フォームを自分のサーバーに送信するだけで、他のサーバーにリクエストがプロキシされ(他のサーバーがIPの不一致に気付くように設定されていない場合)、応答を取得して、好きなものを返します。

于 2010-03-09T15:13:12.710 に答える
6

注意すべきもう1つの重要なこと!!! 上記のでは、使用方法が説明されています

$.ajax({
    type     : 'POST',
    dataType : 'json', 
    url      : 'another-remote-server',
    ...
});

JQuery 1.6以下には、クロスドメインXHRのバグがあります。Firebugによると、OPTIONS以外のリクエストは送信されませんでした。POSTなし。まったく。

コードのテスト/調整に5時間費やしました。リモートサーバー(スクリプト)に多くのヘッダーを追加します。効果なし。しかし後で、JQuery libを1.6.4に更新し、すべてが魅力のように機能します。

于 2012-01-25T17:13:33.303 に答える
5

JQuery AJAX を使用する ASP.net MVC 環境でこれを行う場合は、次の手順に従います (これは、このスレッドで提供されているソリューションの概要です) 。

"caller.com" (任意の Web サイト) が "server.com" (ASP.net MVC アプリケーション) に投稿する必要があるとします。

  1. 「server.com」アプリの Web.config で、次のセクションを追加します。

      <httpProtocol>
          <customHeaders>
              <add name="Access-Control-Allow-Origin" value="*" />
              <add name="Access-Control-Allow-Headers" value="Content-Type" />
              <add name="Access-Control-Allow-Methods" value="POST, GET, OPTIONS" />
          </customHeaders>
      </httpProtocol>
    
  2. 「server.com」では、投稿先のコントローラー (「ホーム」と呼ばれる) で次のアクションを行います。

    [HttpPost]
    public JsonResult Save()
    {
        //Handle the post data...
    
        return Json(
            new
            {
                IsSuccess = true
            });
    }
    
  3. 次に、「caller.com」から、次のようにフォーム (html ID「formId」を持つ) から「server.com」にデータを投稿します。

    $.ajax({
            type: "POST",
            url: "http://www.server.com/home/save",
            dataType: 'json',
            crossDomain: true,
            data: $(formId).serialize(),
            success: function (jsonResult) {
               //do what ever with the reply
            },
            error: function (jqXHR, textStatus) {
                //handle error
            }
        });
    
于 2014-05-06T17:32:46.333 に答える
4

もう1つの方法があります(html5機能を使用)。他のドメインでホストされているプロキシ iframe を使用できます。postMessage を使用してその iframe にメッセージを送信すると、その iframe は POST 要求を (同じドメインで) 実行し、postMessage を応答とともに親ウィンドウに戻すことができます。

sender.com の親

var win = $('iframe')[0].contentWindow

function get(event) {
    if (event.origin === "http://reciver.com") {
        // event.data is response from POST
    }
}

if (window.addEventListener){
    addEventListener("message", get, false)
} else {
    attachEvent("onmessage", get)
}
win.postMessage(JSON.stringify({url: "URL", data: {}}),"http://reciver.com");

reciver.comのiframe

function listener(event) {
    if (event.origin === "http://sender.com") {
        var data = JSON.parse(event.data);
        $.post(data.url, data.data, function(reponse) {
            window.parent.postMessage(reponse, "*");
        });
    }
}
// don't know if we can use jQuery here
if (window.addEventListener){
    addEventListener("message", listener, false)
} else {
    attachEvent("onmessage", listener)
}
于 2014-06-28T06:23:14.157 に答える
3

最良の方法は、クロスオリジンリソースシェアリングポリフィルhttps://github.com/Modernizr/Modernizr/wiki/HTML5-の1つでXMLHttpRequest(jQueryの$ .ajax()、$。post()など)を使用することだと思います。 Cross-Browser-Polyfills#wiki-CORS

于 2011-10-04T09:49:18.667 に答える
3

高レベル.... other-serve.your-server.com が other-server.com を指すように、サーバーに cname をセットアップする必要があります。

あなたのページは、other-server.com へのトランスポートとして機能する非表示の iframe を動的に作成します。次に、JS を介してページから other-server.com に通信し、データをページに返すコールバックを行う必要があります。

可能ですが、your-server.com および other-server.com からの調整が必要です

于 2009-08-19T18:39:46.033 に答える
2

これは古い質問ですが、いくつかの新しいテクノロジーが誰かを助けるかもしれません。

他のサーバーへの管理アクセス権がある場合は、オープンソースのForgeプロジェクトを使用してクロスドメインPOSTを実行できます。Forgeは、FlashのrawソケットAPIを利用するクロスドメインJavaScriptXmlHttpRequestラッパーを提供します。POSTはTLSを介して実行することもできます。

POST先のサーバーへの管理アクセスが必要な理由は、ドメインからのアクセスを許可するクロスドメインポリシーを提供する必要があるためです。

http://github.com/digitalbazaar/forge

于 2010-09-23T17:58:06.353 に答える
1

YQL カスタム テーブル + JS XHR で可能になるはずです。http://developer.yahoo.com/yql/guide/index.html をご覧 ください

クライアント側(js)のhtmlスクレイピングに使用していますが、正常に動作します(完全なオーディオプレーヤーがあり、インターネット/プレイリスト/歌詞/最後のfm情報、すべてのクライアントjs + YQLを検索できます)

于 2010-08-24T15:59:49.930 に答える