AJAX ile alanlar arası uç nokta yükleme


132

AJAX kullanarak etki alanları arası bir HTML sayfası yüklemeye çalışıyorum, ancak dataType "jsonp" olmadığı sürece yanıt alamıyorum. Ancak jsonp kullanıldığında tarayıcı bir betik mime türü bekliyor ancak "text / html" alıyor.

İstek kodum:

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

İstek için jsonp kullanmaktan kaçınmanın bir yolu var mı? CrossDomain parametresini kullanmayı zaten denedim ama işe yaramadı.

Değilse, html içeriğini jsonp'ta almanın herhangi bir yolu yok mu? Şu anda konsol jsonp yanıtında "beklenmedik <" diyor.



Teşekkürler CodeDezk, Bağlantınızın ardından etki alanları arası AJAX istekleri için kendi PHP proxy'mi oluşturdum. Çok kolaydı.
GTS Joe

Yanıtlar:


235

jQuery Ajax Notları

  • Tarayıcı güvenlik kısıtlamaları nedeniyle, çoğu Ajax isteği aynı kaynak politikasına tabidir ; istek, farklı bir etki alanından, alt etki alanından, bağlantı noktasından veya protokolden başarılı bir şekilde veri alamaz.
  • Komut dosyası ve JSONP istekleri, aynı kaynak politikası kısıtlamalarına tabi değildir.

Alanlar arası engelin üstesinden gelmenin bazı yolları vardır :

Etki alanları arası isteklerde yardımcı olan bazı eklentiler vardır :

Dikkat et!

Bu sorunun üstesinden gelmenin en iyi yolu, arka uçta kendi proxy'nizi oluşturmaktır, böylece proxy'niz diğer etki alanlarındaki hizmetleri işaret eder, çünkü arka uçta aynı başlangıç ​​ilkesi kısıtlaması yoktur. Ancak bunu arka planda yapamazsanız, aşağıdaki ipuçlarına dikkat edin.


Uyarı!

Üçüncü taraf proxy'leri kullanmak güvenli bir uygulama değildir, çünkü verilerinizi takip edebilirler, böylece herkese açık bilgilerle kullanılabilir ancak asla özel verilerle kullanılamaz.


Aşağıda gösterilen kod örnekleri jQuery.get () ve jQuery.getJSON () kullanır , her ikisi de jQuery.ajax () 'ın kısa yöntemleridir.


CORS Anywhere

CORS Anywhere, proxy'li isteğe CORS başlıklarını ekleyen bir node.js proxy'sidir .
API'yi kullanmak için, URL'nin önüne API URL'si eklemeniz yeterlidir. (Destekler https : bkz github depo )

Gerektiğinde alanlar arası istekleri otomatik olarak etkinleştirmek istiyorsanız aşağıdaki parçacığı kullanın:

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


Menşei ne olursa olsun

Origin , etki alanları arası bir jsonp erişimidir . Bu, anyorigin.com'a açık kaynaklı bir alternatiftir .

Verileri google.com'dan almak için şu pasajı kullanabilirsiniz:

// 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 Proxy

CORS Proxy, herhangi bir web sitesi için CORS talebini etkinleştirmek için basit bir node.js proxy'sidir . Sitenizdeki javascript kodunun, normalde aynı kaynak politikası nedeniyle engellenecek olan diğer alanlardaki kaynaklara erişmesine izin verir.

O nasıl çalışır? CORS Proxy, HTML 5 ile birlikte eklenen bir özellik olan Çapraz Kaynak Paylaşımından yararlanır. Sunucular, tarayıcıların diğer web sitelerinin barındırdıkları kaynakları talep etmesine izin vermesini istediklerini belirtebilir. CORS Proxy'si, yanıtlara "herkes bunu talep edebilir" diyen bir başlık ekleyen bir HTTP Proxy'sidir.

Bu, hedefe ulaşmanın başka bir yoludur (bkz. Www.corsproxy.com ). Tek yapmanız gereken http: // ve www'yi çıkarmak . vekaleten URL'den alın ve URL'yi başına ekleyinwww.corsproxy.com/

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


CORS proxy tarayıcısı

Son zamanlarda bunu buldum, çeşitli güvenlik odaklı Cross Origin Remote Sharing araçlarını içeriyor. Ancak, arka uç olarak Flash içeren bir kara kutudur.

Burada eylem halinde görebilirsiniz: CORS proxy tarayıcısı
Kaynak kodunu GitHub'dan alın: koto / cors-proxy-browser


4
Ayrıca kendi WhateverOrigin.org sürümünü de dağıtabilirsiniz (veya kodu kendi kullanımınız için taşıyabilirsiniz
EpicVoyage

1
Görüntüler, CSS ve harici javascript başka bir kaynaktan referans alınabilir, bu nedenle yanıtta HTML dizesinin üzerinden geçebilir ve harici kaynakların
src'sini

1
merhaba jherax Bir html sayfası almak için ne olursa olsun kullandım (sadece benim için çalıştı, yql, google vb.) ama ingilizce olmayan karakterler garip. data.contents'ı kodlamayı denedi ancak yardımcı olmadı
user217648

1
Merhaba @Miru, başlığın dediği gibi: "jQuery AJAX ile etki alanları arası html sayfası yükleniyor", etki alanları arası istekleri gerçekleştirmek için bir proxy kullanarak bazı örnekler vererek başlığı yanıtladım. Ayrıca, sorunun ifadesine yanıt olarak, YQL ile JSONP kullanarak etki alanları arası talepler yapmak için bazı bağlantılar verdim. Sizi bağlantıları okumaya davet ediyorum, çok kullanışlıdırlar.
jherax

1
CORS Anywhere yöntemini kullanarak sona erdi $.ajaxPrefilterve harika çalıştı. Çok teşekkürler!
Joshua Pinter

24

Ajax-cross-origin bir jQuery eklentisini kullanabilirsiniz. Bu eklenti ile alanlar jQuery.ajax()arası kullanırsınız . Bunu başarmak için Google hizmetlerini kullanır:

AJAX Cross Origin eklentisi, jSONP'nin uygulanmadığı durumlarda bir proxy jSON alıcı olarak Google Apps Komut Dosyası'nı kullanır. CrossOrigin seçeneğini true olarak ayarladığınızda, eklenti orijinal url'yi Google Apps Komut Dosyası adresiyle değiştirir ve kodlanmış url parametresi olarak gönderir. Google Apps Komut Dosyası, uzak verileri almak ve istemciye JSONP olarak geri döndürmek için Google Sunucuları kaynaklarını kullanır.

Kullanması çok basit:

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

Daha fazlasını buradan okuyabilirsiniz: http://www.ajax-cross-origin.com/


22
Bana kalırsa bu eklenti hiç çalışmadı. Chrome'da hiçbir şey yapmaz.
Michael

Sunucunun kimliğini nasıl doğrulayabilirim?
sttaq

harika çalışıyor! Kullandığım API ne JSONP'yi ne de CORS'u desteklemiyor, bu yüzden işe yarayan tek şey bu. Çok teşekkürler!
JP Lew

jQuery'nin crossOriginseçeneği kesinlikle aynı kökenli ilkeleri hafifletmek için hiçbir şey yapmaz. Yapabilseydim bu yanıtı
Phil

13

Harici site JSONP veya CORS'u desteklemiyorsa, tek seçeneğiniz bir proxy kullanmaktır.

Sunucunuzda bu içeriği isteyen bir komut dosyası oluşturun, ardından sunucunuzdaki komut dizisine ulaşmak için jQuery ajax kullanın.


5

Bunu PHP Sayfanızın başlığına koyun ve API olmadan çalışacaktır:

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

veya

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

veya

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

Nereden $_SERVER['HTTP_ORIGIN']geldiğini merak ediyorum . PHP belgelerinde veya başka bir yerde bulamadım.
Zsolti

Hmm, sadece AJAX istekleriyle doldurulmuş görünüyor. Her neyse, cevap için teşekkürler.
Zsolti

0

Birisinin şu anda karşılaştığım sorunla karşılaşması durumunda bunu gönderiyorum. Birden fazla ayarı düzenlemek, yazıcının mevcut durumunu görmek vb. İçin HTML tabanlı bir kullanıcı arayüzü sunan, ZebraNet yazdırma sunucusuna sahip bir Zebra termal yazıcım var. Görüntülenen yazıcının durumunu almam gerekiyor. ZebraNet sunucusu tarafından sunulan bu html sayfalarından birinde ve örneğin, tarayıcıdaki kullanıcıya bir mesaj () uyarır. Bu, o html sayfasını önce Javascript'te almam gerektiği anlamına geliyor. Yazıcı, kullanıcının bilgisayarının LAN'ı içinde olsa da, Aynı Kaynak Politikasıhala yoluma sıkı sıkıya bağlı kalıyor. JSONP'yi denedim, ancak sunucu html döndürüyor ve işlevselliğini değiştirmenin bir yolunu bulamadım (eğer yapabilseydim, Access-control-allow-origin: * sihirli başlığını zaten ayarlardım). Bu yüzden C # ile küçük bir konsol uygulaması yazmaya karar verdim. Düzgün çalışması için Yönetici olarak çalıştırılması gerekir, aksi takdirde trol yapar: D bir istisna. İşte bazı kodlar:

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

Kullanıcının tek yapması gereken, bu konsol uygulamasını Yönetici olarak çalıştırmaktır. Bunun çok olduğunu biliyorum ... sinir bozucu ve karmaşık, ancak sunucuyu herhangi bir şekilde değiştirememeniz durumunda Etki Alanı İlkesi sorununa bir tür geçici çözüm.

edit: js'den basit bir ajax çağrısı yapıyorum:

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

İstenen sayfanın html'si döndürülür ve veri değişkeninde saklanır .


0

Jherax tarafından önerildiği gibi yerel bir proxy kullanarak veri formunu harici site almak için, içeriği sizin için ilgili harici url'den alan bir php sayfası oluşturabilir ve daha sonra bu php sayfasına bir alma isteği gönderebilirsiniz.

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

php proxy'si olarak https://github.com/cowboy/php-simple-proxy kullanabilirsiniz


0

Sizin URLbu gün çalışmıyor, ancak kod bu çalışma solüsyonu ile güncellenebilir:

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

Tarayıcınızdan talep ettiğiniz hizmeti uygun CORS başlıklarıyla temsil eden CORS proxy'sine ihtiyacınız var . Bu tür hizmetlerin listesi aşağıdaki kod parçacığında bulunmaktadır. Konumunuzdan bu tür hizmetlere ping işlemi görmek için sağlanan kod parçacığını da çalıştırabilirsiniz.

$('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
Bu soruya hiçbir şekilde cevap vermiyor.
0xc0de

@ 0xc0de sonunda cevabı yazdım.
galeksandrp

-7

Anladım. Bunun yerine bunu kullandım.

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

Orada kullandığınız kod alakasız. Önemli olan sunucu tarafı CORS başlıklarıdır.
Quentin
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.