AJAXを使用したクロスドメインエンドポイントの読み込み


131

AJAXを使用してクロスドメインHTMLページをロードしようとしていますが、dataTypeが "jsonp"でないと、応答を取得できません。ただし、jsonpを使用すると、ブラウザはスクリプトのMIMEタイプを想定していますが、「text / html」を受信して​​います。

リクエストのコードは次のとおりです。

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

リクエストにjsonpを使用しないようにする方法はありますか?すでにcrossDomainパラメータを使用しようとしましたが、機能しませんでした。

そうでない場合、jsonpでhtmlコンテンツを受信する方法はありますか?現在、コンソールはjsonp応答で「予期しない<」と言っています。


ここで説明したように、私はproxy.phpを作成することで、問題を解決してきたscode7.blogspot.com/2019/11/...
CodeDezk

回答:


235

jQuery Ajaxノート

  • ブラウザのセキュリティ制限により、ほとんどのAjaxリクエストには同じオリジンポリシーが適用されます。リクエストは、別のドメイン、サブドメイン、ポート、またはプロトコルからデータを正常に取得できません。
  • スクリプトおよびJSONPリクエストは、同じオリジンポリシー制限の対象ではありません。

クロスドメインバリアを克服する方法はいくつかあります。

クロスドメインリクエストに役立つプラグインがいくつかあります。

注意喚起!

この問題を克服する最良の方法は、バックエンドに独自のプロキシを作成することです。これにより、プロキシは他のドメインのサービスをポイントします。これは、バックエンドに同じ発信元ポリシーの制限が存在しないためです。ただし、それをバックエンドで実行できない場合は、次のヒントに注意してください。


警告!

サードパーティのプロキシは、データを追跡できるため、公開情報で使用できるが、プライベートデータで使用できないため、安全な方法ではありません。


以下に示すコード例では、jQuery.get()jQuery.getJSON()を使用しています。どちらもjQuery.ajax()の省略メソッドです


CORS Anywhere

CORS Anywhereは、プロキシされたリクエストにCORSヘッダーを追加するnode.jsプロキシです。
APIを使用するには、URLの前にAPI URLを付けます。(httpsをサポート:githubリポジトリを参照)

必要に応じてクロスドメインリクエストを自動的に有効にする場合は、次のスニペットを使用します。

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


どんな起源

どんなオリジンクロスドメインjsonpアクセスです。これは、anyorigin.comの代替となるオープンソースです

google.comからデータを取得するには次のスニペットを使用できます。

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


CORSプロキシ

CORSプロキシは、任意のWebサイトのCORS要求を有効にする単純なnode.jsプロキシです。これにより、サイトのJavaScriptコードが、同じ生成元のポリシーのために通常はブロックされる他のドメインのリソースにアクセスできるようになります。

どのように機能しますか?CORSプロキシは、HTML 5とともに追加された機能であるクロスオリジンリソースシェアリングを利用します。サーバーは、他のWebサイトがホストするリソースをリクエストすることをブラウザーに許可することをサーバーに指定できます。CORSプロキシは、「誰でも要求できる」という応答にヘッダーを追加する単なるHTTPプロキシです。

これは、目標を達成するもう1つの方法です(www.corsproxy.comを参照)。あなたがしなければならないすべてはhttp://wwwを取り除くことですプロキシされるURLから、URLの前にwww.corsproxy.com/

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


CORSプロキシブラウザー

最近私はこれを見つけました、それは様々なセキュリティ指向のクロスオリジンリモート共有ユーティリティを含みます。しかし、それはバックエンドとしてフラッシュを備えたブラックボックスです。

実際の動作は次の場所で確認できます:CORSプロキシブラウザー
GitHubでソースコードを取得:koto / cors-proxy-browser


4
ここから、独自のバージョンのWhateverOrigin.orgをデプロイ(または独自に使用するためにコードを移植)することもできます:github.com/ripper234/Whatever-Origin
EpicVoyage

1
画像、CSS、外部JavaScriptは別のオリジンから参照できるため、レスポンスでHTML文字列を
調べて

1
こんにちはjherax私はhtmlページを取得するために何でも起源を使用しました(私にとっては唯一の方法で、yql、googleなどを使用しました)。英語以外の文字は奇妙です。data.contentsをエンコードしようとしましたが、助けにはなりませんでした
user217648 2014年

1
こんにちは@Miruです。「jQuery AJAXを使用したクロスドメインHTMLページの読み込み」というタイトルのとおり、プロキシを使用してクロスドメインリクエストを実行する例をいくつか挙げてタイトルに答えました。また、質問の文言に応えて、JSONPとYQLを使用してクロスドメインリクエストを行うためのリンクをいくつか提供しました。リンクをお読みください。非常に役立ちます。
jherax 14

1
でCORS Anywhereメソッドを使用する$.ajaxPrefilterことになり、それはうまくいきました。どうもありがとう!
ジョシュア・ピンター

24

Ajax-cross-origin jQueryプラグインを使用できます。このプラグインでは、jQuery.ajax()クロスドメインを使用します。これを実現するためにGoogleサービスを使用します。

AJAX Cross Originプラグインは、jSONPが実装されていないプロキシjSONゲッターとしてGoogle Apps Scriptを使用します。crossOriginオプションをtrueに設定すると、プラグインは元のURLをGoogle Apps Scriptアドレスに置き換え、エンコードされたURLパラメータとして送信します。Google Apps Scriptは、Googleサーバーリソースを使用してリモートデータを取得し、それをJSONPとしてクライアントに返します。

使い方はとても簡単です。

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

あなたはここでもっと読むことができます:http//www.ajax-cross-origin.com/


22
私に関する限り、このプラグインは機能していません。Chromeでは何もしません。
マイケル

サーバーへの認証方法を教えてください。
sttaq 2015

よく働く!私が使用しているAPIはJSONPもCORSもサポートしていないため、これが機能した唯一のものです。どうもありがとう!
JP Lew 2017

jQueryのcrossOriginオプションは、同じ生成元のポリシーを軽減するために何も実行しません。できればこの回答を削除します
Phil

13

外部サイトがJSONPまたはCORSをサポートしていない場合、唯一の選択肢はプロキシを使用することです。

サーバー上でそのコンテンツを要求するスクリプトを作成し、jQuery ajaxを使用してサーバー上のスクリプトにアクセスします。


5

これをPHPページのヘッダーに挿入するだけで、APIなしでは機能しません。

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

または

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

または

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

どこ$_SERVER['HTTP_ORIGIN']から来るのかしら。PHPのドキュメントや他の場所では見つかりませんでした。
Zsolti

うーん、AJAXリクエストのみが入力されているようです。とにかく、答えてくれてありがとう。
Zsolti

0

私が今直面している同じ問題に誰かが直面した場合に備えて、これを投稿しています。ZebraNetプリントサーバーを備えたZebraサーマルプリンターを持っています。これは、複数の設定を編集したり、プリンターの現在のステータスを確認したりするためのHTMLベースのユーザーインターフェイスを提供します。表示されているプリンターのステータスを取得する必要があります。これらのHTMLページの1つで、ZebraNetサーバーによって提供されます。たとえば、alert()は、ブラウザでユーザーにメッセージを送信します。つまり、最初にJavaScriptでそのHTMLページを取得する必要があります。プリンターはユーザーのPCのLAN内にありますが、その同一生成元ポリシー私の道にはまだしっかりと残っています。JSONPを試しましたが、サーバーはhtmlを返し、その機能を変更する方法が見つかりませんでした(可能な場合は、マジックヘッダーAccess-control-allow-origin:*を既に設定しているはずです)。そこで、小さなコンソールアプリをC#で作成することにしました。正しく動作するには、管理者として実行する必要があります。そうしないと、例外:Dがトロールされます。ここにいくつかのコードがあります:

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

ユーザーが行う必要があるのは、そのコンソールアプリを管理者として実行することだけです。私もそれが方法であることを知っています...イライラして複雑ですが、サーバーを変更できない場合のドメインポリシーの問題に対する一種の回避策です。

編集:jsから私は単純な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);
                }
            });

要求されたページのhtmlが返され、データ変数に格納されます。


0

jheraxの提案に従ってローカルプロキシを使用して渡すことで外部サイトからデータを取得するには、それぞれの外部URLからコンテンツを取得するphpページを作成し、そのphpページにgetリクエストを送信します。

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

PHPプロキシとして、https://github.com/cowboy/php-simple-proxyを使用できます


0

あなたは、URLこれらの日は動作しませんが、あなたのコードは、このワーキング溶液を用いて更新することができます。

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>


-2

ブラウザからのリクエストを適切なCORSヘッダーでリクエストされたサービスにプロキシするCORSプロキシが必要です。そのようなサービスのリストは、以下のコードスニペットにあります。提供されたコードスニペットを実行して、現在地からそのようなサービスへのpingを確認することもできます。

$('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>


11
これは決して質問に答えるものではありません。
0xc0de

@ 0xc0deようやく答えを書きました。
galeksandrp

-7

理解した。代わりにこれを使用しました。

$('.div_class').load('http://en.wikipedia.org/wiki/Cross-origin_resource_sharing #toctitle');

そこで使用したコードは無関係です。重要なのはサーバー側のCORSヘッダーです。
クエンティン2015年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.