XmlHttpRequest hatası: Access-Control-Allow-Origin tarafından orijin null değerine izin verilmiyor


550

JQuery'nin AJAX desteği ile Flickr ve Panoramio'dan görüntü çeken bir sayfa geliştiriyorum.

Flickr tarafı iyi çalışıyor, ancak $.get(url, callback)Panoramio'dan denediğimde Chrome konsolunda bir hata görüyorum:

XMLHttpRequest http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=processImages&minx=-30&miny=0&maxx=0&maxy=150 yükleyemez . Access-Control-Allow-Origin tarafından orijin null değerine izin verilmiyor.

Bu URL'yi doğrudan bir tarayıcıdan sorgularsam iyi çalışır. Neler oluyor ve bunun üstesinden gelebilir miyim? Sorgumu yanlış oluşturuyor muyum, yoksa bu Panoramio'nun yapmaya çalıştığım şeyi engellemek için yaptığı bir şey mi?

Google, hata mesajında yararlı bir eşleşme getirmedi .

DÜZENLE

Sorunu gösteren bazı örnek kodlar şunlardır:

$().ready(function () {
  var url = 'http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=processImages&minx=-30&miny=0&maxx=0&maxy=150';

  $.get(url, function (jsonp) {
    var processImages = function (data) {
      alert('ok');
    };

    eval(jsonp);
  });
});

Şunları yapabilirsiniz çevrimiçi örnek çalıştırmak .

DÜZENLEME 2

Bu konudaki yardımı için Darin'e teşekkürler. YUKARI KOD YANLIŞ. Bunun yerine şunu kullanın:

$().ready(function () {
  var url = 'http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&minx=-30&miny=0&maxx=0&maxy=150&callback=?';

  $.get(url, function (data) {
    // can use 'data' in here...
  });
});

1
Ne yapar İsteği yapıyoruz gibi URL bakmak gelen ? Bu dinamik olarak oluşturulmuş olması olmaz iframesen misin document.write, örneğin içine?
Pekka

5
HTTP yanıtını isteklerden her hizmete gönderebilir misiniz? Eminim Panoramio Access-Control-Allow-Origin'i sunmuyor. Örnekler için w3.org/TR/cors adresine bakın .
Kevin Hakanson

2
@Kevin, sunucu JSONP gönderirse bu başlıklara ihtiyacınız yoktur.
Darin Dimitrov

@Pekka, şu anda yerel makinemden sayfayı çalıştırıyorum ( file:///C:/). Hayır iframedahil.
Drew Noakes

1
@drew bir http URL'sinden çalıştırırsanız ne olur? Bu şekilde bir fark yaratmamalı, sadece olasılığı dışlamak için.
Pekka

Yanıtlar:


423

Kayıt için, anlayabildiğim kadarıyla, iki probleminiz vardı:

  1. "Jsonp" türü bir belirteci geçmiyordunuz $.get, bu nedenle sıradan bir XMLHttpRequest kullanıyordu. Ancak, tarayıcınız, sunucu bunu onayladıysa, etki alanları arası XMLHttpRequest öğesine izin vermek için CORS (Kaynaklar Arası Kaynak Paylaşımı) özelliğini destekledi. İşte bu noktada Access-Control-Allow-Originbaşlık geldi.

  2. İnanıyorum ki bir dosyadan çalıştırdığınızı söylemiştiniz: // URL. CORS üstbilgilerinin, etki alanları arası bir XHR'nin uygun olduğunu bildirmesinin iki yolu vardır. Biri göndermek Access-Control-Allow-Origin: *(eğer, eğer Flickr'a ulaşıyorduysanız $.get, yapmaları gerekirdi), diğeri ise Originbaşlığın içeriğini yankılamaktı . Ancak, file://URL'ler Originyankı yoluyla yetkilendirilemeyen bir null değeri üretir .

Birincisi, Darin'in kullanma önerisiyle dolambaçlı bir şekilde çözüldü $.getJSON. callback=?URL'de alt dizeyi görürse istek türünü varsayılan "json" yerine "jsonp" olarak değiştirmek biraz sihir yapar .

Bu, ikincisini artık bir file://URL'den bir CORS isteği gerçekleştirmeye çalışmadan çözdü .

Diğer kişilere açıklık getirmek için basit sorun giderme talimatları şunlardır:

  1. JSONP kullanmaya çalışıyorsanız, aşağıdakilerden birinin olduğundan emin olun:
    • Sen kullanıyorsanız $.getve set dataTypeiçin jsonp.
    • URL'yi kullanıyorsunuz $.getJSONve callback=?URL'ye ekliyorsunuz.
  2. CORS üzerinden bir etki alanları arası XMLHttpRequest yapmaya çalışıyorsanız ...
    1. Üzerinden test ettiğinizden emin olun http://. Aracılığıyla çalışan komut dosyalarının file://CORS için sınırlı desteği vardır.
    2. Tarayıcının gerçekten CORS'yi desteklediğinden emin olun . (Opera ve Internet Explorer partiye geç kaldı)

45
Peki bunun çözümü nedir?
jQuerybeast

19
Geri arama =? FTW
Tim

10
Chrome gibi bazı tarayıcılar, dosyalardan --allow-file-access-access
echox

1
callback=?benim için çalışmadı, ama jsonp=?yaptı. Bunun için bir açıklama var mı?
crunkchitis

1
Test etmek için bir web sunucusu yüklemem gerekir http://mi? Yoksa bu protokolü kullanarak dosyayı açmanın bir yolu var mı?
Will Sewell

76

Belki denilen komut dosyasına bir HEADER eklemeniz gerekir, işte PHP'de yapmam gereken şey:

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

Alanlar arası AJAX ou hizmetleri WEB (Fransızca) ile ilgili daha fazla ayrıntı .


1
@Uri: HTTP sunucunuza bağlıdır. Apache ile mod_headers'a bakmak isteyeceksiniz.
ssokolow

4
@Uri <meta http-equiv = "Erişim-Denetim-İzin Verme Kökenli" content = "*">
Herberth Amaral

7
@HerberthAmaral Bunu <head> </head> içine eklemeyi denedim, ama benim için çalışmıyor. İOS Safari ve Chrome'da deniyorum, ancak konsolda, erişim-Kontrol-İzin Ver-Kökeni hatası tarafından başlangıç ​​konumuna null izin verilmiyor.
thandasoru

3
Güvenlik nedeniyle html dosyasının başında çalışmaz. Bir başlık olmalı. stackoverflow.com/questions/7015782/…
Justin Blank

HTML'de olamaz. HTML sayfasını tarayıcınıza ağ üzerinden gönderen program tarafından belirtilmelidir (web sunucusu denir).
Roman Plášil

70

Basit bir HTML projesi için:

cd project
python -m SimpleHTTPServer 8000

Ardından dosyanıza göz atın.


1
müthiş ve çalışır, 0.0.0.0:8000 gidin ve POSTolsun istekleri deneyin : code 501, message Unsupported method ('POST')googles için.
pjammer

"Bir Python web sunucusu (örneğin cherrypy gibi) 0.0.0.0'da hizmet verdiğini söylediğinde, istenen ana bilgisayar adı veya IP ne olursa olsun bu makinede sonlanan tüm TCP trafiğini dinlediği anlamına gelir." Belki de localhost'a mesaj göndermeyi deneyin: 8000 stackoverflow.com/a/4341808/102022
eric.christensen

20

Google Chrome v5.0.375.127'de benim için çalışıyor (uyarıyı alıyorum):

$.get('http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=?&minx=-30&miny=0&maxx=0&maxy=150',
function(json) {
    alert(json.photos[1].photoUrl);
});

Ayrıca $.getJSON()önceki IE8 (en azından makinemde) üzerinde çalışmadığı için yerine yöntemini kullanmanızı tavsiye ederim :

$.getJSON('http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=?&minx=-30&miny=0&maxx=0&maxy=150', 
function(json) {
    alert(json.photos[1].photoUrl);
});

Buradan çevrimiçi olarak deneyebilirsiniz .


GÜNCELLEME:

Kodunuzu gösterdiğinize göre, onunla ilgili sorunu görebiliyorum. Hem anonim hem de satır içi işleviniz var, ancak her ikisi de çağrılacak processImages. JQuery'nin JSONP desteği böyle çalışır. callback=?Anonim bir işlev kullanabilmeniz için nasıl tanımladığımı fark edin . Bununla ilgili daha fazla bilgiyi dokümantasyonda okuyabilirsiniz .

Başka bir açıklama, eval dememelisiniz. Anonim işlevinize iletilen parametre jQuery tarafından zaten JSON'a ayrıştırılacaktır.


Hmm tamam tekrar deneyeyim. Chrome btw "6.0.472.51 beta" nın farklı bir sürümündeyim.
Drew Noakes

Kodun benim için çalıştı. Sorumu olsa sorunu ortaya çıkaran bazı kod ile güncelledim.
Drew Noakes

Teşekkürler getJSON için teşekkürler ... Ben jsFiddle örnek sorunu göstermek için çatal ( jsfiddle.net/ZfvKm ) ve şimdi XMLHttpRequest panoramio.com/wapi/data/… yükleyemez
Drew Noakes

@Darin, güncelleme için teşekkürler. Ne demek istediğini görüyorum ve bunun birkaç kombinasyonuyla oynadım, ama henüz döndürülen nesneye erişmenin bir yolunu bulamıyorum. Verilere erişim göstermek için jsFiddle örneğinizi güncelleyebilir misiniz? Geri aramayı bu şekilde ayarlarsanız, ?döndürülen JSON parantez içine alınır. Geri arama işleviniz için bir parametre tanımlamıyorsunuz ve değeri thisbir yanıt nesnesine sahip görünmüyor (en azından .datadeğer null).
Drew Noakes

@Darin, harika. Çok teşekkürler. Şimdi iyi çalışıyor. Bunu okuyan herkes için, dahil edilmesi callback=?jQuery'ye dahili olarak rastgele bir işlev adı üretmesini söyler ve bu da geçtiğiniz anonim işleve çağrı ile sonuçlanır .getJSON. Takdir.
Drew Noakes

8

İstenen sunucu JSON veri biçimini desteklediği sürece JSONP (JSON Padding) arabirimini kullanın. Proxy sunucuları veya süslü başlık öğeleri olmadan harici etki alanı istekleri yapmanızı sağlar.



4

http.confDosya üzerinden yönettik (HTTP hizmetini düzenledik ve yeniden başlattık):

<Directory "/home/the directory_where_your_serverside_pages_is">
    Header set Access-Control-Allow-Origin "*"
    AllowOverride all
    Order allow,deny
    Allow from all
</Directory>

Alanına, Header set Access-Control-Allow-Origin "*"kesin bir URL koyabilirsiniz.


1
bu XAMPP'nin Apache'sinde çalışmaz. sorun hala var.
Raptor

1
Bu güvensiz. Neden bakın; stackoverflow.com/questions/7564832/…
Rob

@RobQuist'in dediği gibi güvensiz.
d337

4

Yerel test yapıyorsanız veya dosyayı böyle bir şeyden çağırıyorsanız, file://tarayıcı güvenliğini devre dışı bırakmanız gerekir.

MAC'de: open -a Google\ Chrome --args --disable-web-security


3

Benim durumumda, aynı kod Firefox'ta iyi çalıştı, ancak Google Chrome'da işe yaramadı. Google Chrome'un JavaScript konsolu şunları söyledi:

XMLHttpRequest cannot load http://www.xyz.com/getZipInfo.php?zip=11234. 
Origin http://xyz.com is not allowed by Access-Control-Allow-Origin.
Refused to get unsafe header "X-JSON"

Ben kaynak URL ile doğru eşleşmesi için Ajax URL www kısmını bırakmak zorunda kaldı ve o zaman iyi çalıştı.


2

Tüm sunucular jsonp'yi desteklemez. Sunucunun sonuçlarında geri arama işlevini ayarlaması gerekir. Ben saf json döndüren ancak jsonp desteklemeyen sitelerden json yanıtları almak için bunu kullanın:

function AjaxFeed(){

    return $.ajax({
        url:            'http://somesite.com/somejsonfile.php',
        data:           {something: true},
        dataType:       'jsonp',

        /* Very important */
        contentType:    'application/json',
    });
}

function GetData() {
    AjaxFeed()

    /* Everything worked okay. Hooray */
    .done(function(data){
        return data;
    })

    /* Okay jQuery is stupid manually fix things */
    .fail(function(jqXHR) {

        /* Build HTML and update */
        var data = jQuery.parseJSON(jqXHR.responseText);

        return data;
    });
}

1

Apache sunucusu kullanıyorum, bu yüzden mod_proxy modülünü kullandım. Modülleri etkinleştir:

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

Sonra Ekle:

ProxyPass /your-proxy-url/ http://service-url:serviceport/

Son olarak, komut dosyanıza proxy-url iletin.



1

PHP için - Bu benim için Chrome, safari ve firefox'ta çalışıyor

https://w3c.github.io/webappsec-cors-for-developers/#avoid-returning-access-control-allow-origin-null

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

axios kullanarak php live services dosyasını şu dosya ile arayın: //


Bu da bana çalışır, gerçek NULL değil null bir STRING olduğunu fark edin. Ben header('Access-Control-Allow-Origin: '.( trim($_SERVER['HTTP_REFERER'],'/') ?:'null'),true);uzak bir sunucudan diğerine çapraz kökenli izin ve yerel dosya için (dize) null düşmek olarak kullanın.
Louis Loudog Trottier

0

Chrome'da da aynı hatayı aldım (diğer tarayıcıları test etmedim). Www.domain.com yerine domain.com adresinde geziniyor olmamdan kaynaklanıyordu. Biraz garip, ama .htaccess'e aşağıdaki satırları ekleyerek sorunu çözebilirim. Domain.com adresini www.domain.com adresine yönlendirir ve sorun çözülmüştür. Neredeyse hiç www yazın ama tembel bir web ziyaretçisiyim ama görünüşe göre bazı durumlarda gerekli.

RewriteEngine on
RewriteCond %{HTTP_HOST} ^domain\.com$ [NC]
RewriteRule ^(.*)$ http://www.domain.com/$1 [R=301,L]


0

Millet,

Benzer bir sorunla karşılaştım. Ama Fiddler'ı kullanarak bu konuya girebildim. Sorun, Web API tarafında CORS uygulamasında yapılandırılan istemci URL'sinin sonunda eğik çizgi olmaması gerektiğidir. İsteğinizi Google Chrome üzerinden gönderdikten ve Fiddler’ın Üstbilgiler bölümünün TextView sekmesini inceledikten sonra hata mesajı şuna benzer:

* "Belirtilen politika kaynağı sizin_client_url: / 'geçersiz. Eğik çizgi ile bitemez ."

Bu çok ilginç çünkü Internet Explorer'da herhangi bir sorun olmadan çalıştı, ancak Google Chrome kullanarak test ederken bana bir baş ağrısı verdi.

CORS kodundaki eğik çizgiyi kaldırdım ve Web API'sını yeniden derledim ve şimdi API'ya Chrome ve Internet Explorer aracılığıyla herhangi bir sorun olmadan erişilebilir. Lütfen bunu deneyin.

Teşekkürler Andy


0

Yukarıdaki CodeGroover tarafından gönderilen çözümde küçük bir sorun var , burada bir dosyayı değiştirirseniz, güncellenmiş dosyayı gerçekten kullanmak için sunucuyu yeniden başlatmanız gerekir (en azından benim durumumda).

Biraz arama Yani buldum bu bir kullanmak için:

sudo npm -g install simple-http-server # to install
nserver # to use

Ve sonra hizmet edecek http://localhost:8000.


1
Bu bağlantı soruyu cevaplayabilse de, cevabın temel kısımlarını buraya eklemek ve bağlantıyı referans olarak sağlamak daha iyidir. Bağlantı verilen sayfa değişirse, yalnızca bağlantı yanıtları geçersiz olabilir. - Yorumdan
Vi100

Bağlantı netleştirildi.
MiJyn
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.