web-dev-qa-db-ja.com

AJAXクロスドメインコール

AJAXクロスドメインポリシーについて知っています。だから、ajax HTTPリクエストを介して " http://www.google.com "を呼び出すことはできません。結果は私のサイトのどこかにあります。

DataType "jsonp"で試しましたが、実際には動作しますが、構文エラーが表示されます(明らかに、受信したデータがJSON形式ではないため)

外部ドメインからデータを受信/表示する他の可能性はありますか? iFrameは同じポリシーに従いますか?

65
jAndy

AJAXを使用してクロスドメインデータを取得する唯一の(簡単な)方法は、 Andy E のようにプロキシとしてサーバー側の言語を使用することです。 jQueryを使用して実装するには:

JQueryパーツ:

$.ajax({
    url: 'proxy.php',
    type: 'POST',
    data: {
        address: 'http://www.google.com'
    },
    success: function(response) {
        // response now contains full HTML of google.com
    }
});

そしてPHP(proxy.php):

echo file_get_contents($_POST['address']);

そのような単純な。スクレイピングされたデータを使用してできること、またはできないことだけに注意してください。

66
Tatu Ulmanen

データを参照するページにスクリプトタグを動的に挿入する必要があります。 JSONPを使用すると、スクリプトがロードされたときにコールバック関数を実行できます。

[〜#〜] jsonp [〜#〜] のウィキペディアページには簡潔な例があります。スクリプトタグ:

<script type="text/javascript" src="http://domain1.com/getjson?jsonp=parseResponse">
</script>

parseResponseへの呼び出しにラップされたJSONデータを返します。

parseResponse({"Name": "Cheeso", "Rank": 7})

(domain1.comのgetjsonスクリプトの構成に依存)

タグを動的に挿入するコードは次のようになります。

var s = document.createElement("script");
s.src = "http://domain1.com/getjson?jsonp=parseResponse";
s.type = "text/javascript";
document.appendChild(s);
19
alunny

[〜#〜] yql [〜#〜] を使用して、独自のプロキシをホストする必要なくリクエストを実行できます。コマンドを実行しやすくするために、単純な関数を作成しました。

function RunYQL(command, callback){
     callback_name = "__YQL_callback_"+(new Date()).getTime();
     window[callback_name] = callback;
     a = document.createElement('script');
     a.src = "http://query.yahooapis.com/v1/public/yql?q="
             +escape(command)+"&format=json&callback="+callback_name;
     a.type = "text/javascript";
     document.getElementsByTagName("head")[0].appendChild(a);
}

JQueryがある場合は、代わりに$ .getJSONを使用できます。

サンプルは次のとおりです。

RunYQL('select * from html where url="http://www.google.com/"',
       function(data){/* actions */}
);
16

残念ながら(または幸いなことに)そうではありません。クロスドメインポリシーには理由があります。簡単に回避できる場合、セキュリティ対策としてはあまり効果的ではありません。 JSONP以外、唯一のオプションは 独自のサーバーを使用してページをプロキシする です。

Iframeでは、それらは同じポリシーの対象となります。もちろん、外部ドメインからのデータを表示することはできますが、それを操作することはできません。

11
Andy E

このコードをクロスドメインAjax呼び出しに使用します。ここで複数のコードが役立つことを願っています。私はPrototypeライブラリを使用していますが、JQueryやDojoなどでも同じことができます:

ステップ1:新しいjsファイルを作成し、このクラスを内部に配置して、xss_ajax.jsという名前を付けました

var WSAjax = Class.create ({
    initialize: function (_url, _callback){
        this.url = _url ;
        this.callback = _callback ;
        this.connect () ;
    },
    connect: function (){
        var script_id = null;
        var script = document.createElement('script');
        script.setAttribute('type', 'text/javascript');
        script.setAttribute('src', this.url);
        script.setAttribute('id', 'xss_ajax_script');

        script_id = document.getElementById('xss_ajax_script');
        if(script_id){
            document.getElementsByTagName('head')[0].removeChild(script_id);
        }

        // Insert <script> into DOM
        document.getElementsByTagName('head')[0].appendChild(script);
    },
    process: function (data){
        this.callback(data) ;
    }

}) ;

このクラスは、src属性がJSONデータプロバイダーをターゲットとする動的なスクリプト要素を作成します(実際には、JSON-Pは遠隔サーバーがこの形式でデータを提供する必要があるため::: call_back_function(// json_data_here)::スクリプトタグが作成されると、 JSONは関数として直接評価されます(ステップ2でコールバックメソッド名をサーバーに渡すことについて説明します)。この背後にある主な概念は、img要素のようなスクリプトがSOP制約に関係しないということです。

Step2:XHTTPRequestオブジェクトを使用するAJAXの代わりに、JSONを非同期的にプルしたいHTMLページ(これをAJAJ〜Asynchronous JAvascript + JSON :-)と呼びます)

//load Prototype first
//load the file you've created in step1


var xss_crawler = new WSAjax (
     "http://your_json_data_provider_url?callback=xss_crawler.process"
 ,   function (_data){
            // your json data is _data and do whatever you like with it 
        }) ;

ステップ1でコールバックを覚えていますか?そのため、サーバーに渡し、そのメソッドに埋め込まれたJSONを返します。この場合、サーバーは評価可能なjavascriptコードxss_crawler.process(// the_json_data)を返します。xss_crawlerはWSAjaxクラスのインスタンスであることを思い出してください。サーバーコードはユーザーに依存します(ユーザーの場合)が、ほとんどのAjaxデータプロバイダーでは、パラメーターでコールバックメソッドを指定できます。 RubyのRailsで

render :json=>MyModel.all(:limit=>10), :callback => params[:callback],:content_type => "application/json"

これですべて、JSON形式のみのアプリ(ウィジェット、マップなど)から別のドメインからデータを取得できるようになりました。忘れないでください。

あなたの忍耐に感謝します:-)、コードのフォーマットに平和と申し訳ありませんが、うまく機能しません

4
R Francky

いくつかの調査を行った後、この問題の唯一の「解決策」は以下を呼び出すことです:

if($.browser.mozilla)
   netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead');

これにより、ユーザーにWebサイトの継続を許可するかどうかが尋ねられます。彼がそれを確認した後、データ型に関係なくすべてのajaxコールが実行されます。

これは、Mozillaブラウザーで機能します。IE <8、ユーザーは同様の方法でクロスドメインコールを許可する必要があり、一部のバージョンはブラウザーオプション内で構成する必要があります。

chrome/safari:今のところ、これらのブラウザの設定フラグは見つかりませんでした。

jSONPをデータ型として使用するのは良いことですが、私の場合、アクセスする必要があるドメインがその形式のデータをサポートしているかどうかはわかりません。

別のショットは、クロスドメインでも機能するHTML5 postMessageを使用することですが、ユーザーをHTML5ブラウザーに破滅させる余裕はありません。

4
jAndy

Phpスクリプトを使用してリモートサーバーから回答を取得している場合は、最初に次の行を追加します。

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

私の意見では、JSONPが最良の選択肢です。構文エラーが発生する理由を理解してください-受信したデータがJSONではないことを確認してください。それから多分あなたは何とか間違ったAPIを使用しています。

あなたが使用できる別の方法ですが、私はそれがあなたの場合に適用されるとは思わない、srcがあなたが呼び出したいドメインにあるページにiFrameを持っています。呼び出しを行わせてから、JSを使用してiFrameとページ間で通信します。これは、クロスドメインをバイパスしますが、呼び出したいドメインにiFrameのsrcがある場合のみです。

2
Nir

ここでは、空想やJSONを使用しなくても、簡単に実行できる方法を示します。

最初に、リクエストを処理するサーバー側スクリプトを作成します。 http://www.example.com/path/handler.php のようなもの

次のようなパラメータで呼び出します:.../handler.php?param1 = 12345&param2 = 67890

その中で、受信したデータを処理した後、output

document.serverResponse('..all the data, in any format that suits you..');
// Any code could be used instead, because you dont have to encode this data
// All your output will simply be executed as normal javascript

次に、クライアント側のスクリプトで、次を使用します。

document.serverResponse = function(param){ console.log(param) }

var script = document.createElement('script');
script.src='http://www.example.com/path/handler.php?param1=12345&param2=67890';
document.head.appendChild(script);

このアプローチの唯一の制限は、サーバーに送信できるパラメーターの最大長です。ただし、複数のリクエストをいつでも送信できます。

1
AlexTR

テクノロジーCORSを使用して、両方のサーバー(Javascriptが実行されているサーバーと外部APIサーバー)を構成できます。

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

p.s .:答え https://stackoverflow.com/a/37384641/6505594 もこのアプローチを提案しており、外部APIサーバーを他の全員に開放して呼び出しています。

0
morhook