Errore XmlHttpRequest: Origin null non è consentito da Access-Control-Allow-Origin


550

Sto sviluppando una pagina che estrae immagini da Flickr e Panoramio tramite il supporto AJAX di jQuery.

La parte di Flickr funziona bene, ma quando provo $.get(url, callback)da Panoramio, vedo un errore nella console di Chrome:

XMLHttpRequest non può caricare 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 . L'origine null non è consentita da Access-Control-Allow-Origin.

Se eseguo una query dell'URL direttamente da un browser, funziona perfettamente. Cosa sta succedendo e posso aggirare questo? Sto componendo la mia domanda in modo errato, o è qualcosa che Panoramio fa per ostacolare ciò che sto cercando di fare?

Google non ha mostrato alcuna corrispondenza utile sul messaggio di errore .

MODIFICARE

Ecco un codice di esempio che mostra il problema:

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

Puoi eseguire l'esempio online .

MODIFICA 2

Grazie a Darin per il suo aiuto in questo. IL CODICE SOPRA È ERRATO. Usa questo invece:

$().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
Che cosa significa l'aspetto URL del tipo che si stanno facendo la richiesta da ? Questo non capita di essere un generati dinamicamente iframeche document.writein, per esempio?
Pekka,

5
Puoi pubblicare la risposta HTTP dalla richiesta a ciascun servizio. Scommetto che Panoramio non sta offrendo Access-Control-Allow-Origin. Vedi w3.org/TR/cors per esempi.
Kevin Hakanson,

2
@Kevin, non hai bisogno di quelle intestazioni se il server invia JSONP.
Darin Dimitrov,

@Pekka, al momento sto eseguendo la pagina dal mio computer locale ( file:///C:/). No iframeè coinvolto.
Drew Noakes,

1
@drew cosa succede se lo esegui da un URL http? Non dovrebbe fare la differenza in questo modo, ma solo per escludere la possibilità.
Pekka,

Risposte:


423

Per la cronaca, per quanto posso dire, hai avuto due problemi:

  1. Non stavi passando un identificatore di tipo "jsonp" al tuo $.get, quindi utilizzava un normale XMLHttpRequest. Tuttavia, il tuo browser supporta CORS (Cross-Origin Resource Sharing) per consentire XMLHttpRequest tra domini se il server lo ha OK. Ecco dove è Access-Control-Allow-Originarrivata l' intestazione.

  2. Credo che tu abbia detto che lo stavi eseguendo da un file: // URL. Esistono due modi per le intestazioni CORS per segnalare che un XHR tra domini è OK. Uno è quello di inviare Access-Control-Allow-Origin: *(che, se stavate raggiungendo Flickr tramite $.get, dovevano averlo fatto) mentre l'altro doveva ripetere il contenuto Origindell'intestazione. Tuttavia, gli file://URL producono un valore nullo Originche non può essere autorizzato tramite eco-back.

Il primo è stato risolto in modo circolare dal suggerimento di Darin di utilizzare $.getJSON. Fa un po 'di magia cambiare il tipo di richiesta dal suo valore predefinito di "json" a "jsonp" se vede la sottostringa callback=?nell'URL.

Ciò ha risolto il secondo non tentando più di eseguire una richiesta CORS da un file://URL.

Per chiarire altre persone, ecco le semplici istruzioni per la risoluzione dei problemi:

  1. Se stai tentando di utilizzare JSONP, assicurati che si verifichi una delle seguenti situazioni:
    • Stai utilizzando $.gete impostato dataTypesu jsonp.
    • Stai utilizzando $.getJSONe incluso callback=?nell'URL.
  2. Se stai cercando di eseguire una richiesta XMLHttp tra domini tramite CORS ...
    1. Assicurati di provare tramite http://. Gli script eseguiti tramite file://hanno un supporto limitato per CORS.
    2. Assicurarsi che il browser supporti effettivamente CORS . (Opera e Internet Explorer sono in ritardo alla festa)

45
Qual è la soluzione a questo?
jQuerybeast,

19
callback =? FTW
Tim

10
Alcuni browser come Chrome consentono CORS se avviato con il parametro --allow-file-access-from-files
echox

1
callback=?non ha funzionato per me, ma jsonp=?ha funzionato. Qualche spiegazione per quello?
Crunkchitis,

1
Devo installare un server web per testare tramite http://? O c'è un modo per aprire semplicemente il file usando quel protocollo?
Will Sewell,

76

Forse devi aggiungere un HEADER nel tuo script chiamato, ecco cosa dovevo fare in PHP:

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

Maggiori dettagli in Servizi di domini AJAX o WEB WEB (in francese).


1
@Uri: dipende dal tuo server HTTP. Con Apache, ti consigliamo di esaminare mod_headers.
ssokolow,

4
@Uri <meta http-equiv = "Access-Control-Allow-Origin" content = "*">
Herberth Amaral

7
@HerberthAmaral Ho provato ad aggiungere questo in <head> </head>, ma per me non funziona. Lo sto provando in iOS Safari e Chrome, ma nella console ottengo l'origine null non consentita dall'errore Access-Control-Allow-Origin.
Thandasoru,

3
Non funziona nella testa del file html per motivi di sicurezza. Deve essere un'intestazione. stackoverflow.com/questions/7015782/…
Justin Blank

Non può essere nell'HTML. Deve essere specificato dal programma che sta inviando la pagina HTML al browser in rete (il cosiddetto web server).
Roman Plášil,

70

Per un semplice progetto HTML:

cd project
python -m SimpleHTTPServer 8000

Quindi sfoglia il tuo file.


1
mentre fantastico e funziona, quando vai a 0.0.0.0:8000 e provi le POSTrichieste che ottieni: code 501, message Unsupported method ('POST')per i googles.
Pjammer,

"Quando un server Web Python (come Cherrypy per esempio) dice che sta servendo su 0.0.0.0 significa che sta ascoltando tutto il traffico TCP che finisce su quella macchina, indipendentemente dal nome host o IP richiesto." Così forse prova a pubblicare a localhost: 8000 stackoverflow.com/a/4341808/102022
eric.christensen

20

Funziona per me su Google Chrome v5.0.375.127 (ricevo l'avviso):

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

Inoltre, ti consiglio di utilizzare il $.getJSON()metodo, poiché il precedente non funziona su IE8 (almeno sulla mia macchina):

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

Puoi provarlo online da qui .


AGGIORNARE:

Ora che hai mostrato il tuo codice posso vedere il problema con esso. Stai avendo sia una funzione anonima che una funzione incorporata ma entrambe verranno chiamate processImages. Ecco come funziona il supporto JSONP di jQuery. Si noti come sto definendo il callback=?modo che è possibile utilizzare una funzione anonima. Puoi leggere di più al riguardo nella documentazione .

Un'altra osservazione è che non dovresti chiamare eval. Il parametro passato alla funzione anonima verrà già analizzato in JSON da jQuery.


Hmm ok fammi riprovare. Sono su una versione diversa di Chrome tra "6.0.472.51 beta".
Drew Noakes,

Il tuo codice ha funzionato per me. Ho aggiornato la mia domanda con del codice che risolve il problema.
Drew Noakes,

Grazie per la punta su getJSON ... Ho mostrato il tuo esempio jsFiddle per mostrare il problema ( jsfiddle.net/ZfvKm ) e ora vedo il messaggio di errore XMLHttpRequest non è possibile caricare panoramio.com/wapi/data/… . Origin fiddle.jshell.net non è consentito da Access-Control-Allow-Origin.
Drew Noakes,

@Darin, grazie per l'aggiornamento. Vedo il tuo punto e ho giocato con alcune combinazioni di questo, ma devo ancora trovare un modo per accedere all'oggetto restituito. Potresti aggiornare il tuo esempio di jsFiddle per mostrare l'accesso ai dati? Se si imposta il callback su, ?il JSON restituito è racchiuso tra parentesi. Non si definisce un parametro per la funzione di callback e il valore di thisnon sembra avere un oggetto response (almeno, il .datavalore è null).
Drew Noakes,

@Darin, fantastico. Grazie molto. Funziona bene ora. Per chiunque legga questo, l'inclusione di callback=?dice a jQuery di generare internamente un nome di funzione casuale, risultante in una chiamata alla funzione anonima a cui si passa .getJSON. Apprezzato.
Drew Noakes,

8

Finché il server richiesto supporta il formato dati JSON, utilizzare l'interfaccia JSONP (JSON Padding). Ti consente di effettuare richieste di dominio esterno senza server proxy o elementi di intestazione elaborati.



4

Lo abbiamo gestito tramite il http.conffile (modificato e quindi riavviato il servizio HTTP):

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

Nel Header set Access-Control-Allow-Origin "*", puoi inserire un URL preciso.


1
questo non funziona su Apache di XAMPP. il problema esiste ancora.
Raptor

1
Questo non è sicuro. Vedi qui perché; stackoverflow.com/questions/7564832/…
Rob,

Non è sicuro come ha detto @RobQuist.
d337,

4

Se stai eseguendo test locali o chiamando il file da qualcosa del genere, file://devi disabilitare la sicurezza del browser.

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


3

Nel mio caso, lo stesso codice ha funzionato bene su Firefox, ma non su Google Chrome. La console JavaScript di Google Chrome ha dichiarato:

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"

Ho dovuto abbandonare la parte www dell'URL Ajax perché corrispondesse correttamente all'URL di origine e allora ha funzionato bene.


2

Non tutti i server supportano jsonp. Richiede che il server imposti la funzione di callback nei suoi risultati. Lo uso per ottenere risposte json da siti che restituiscono json puro ma non supportano jsonp:

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

Uso il server Apache, quindi ho usato il modulo mod_proxy. Abilita moduli:

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

Quindi aggiungere:

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

Infine, passa proxy-url al tuo script.


1

Come nota finale la documentazione di Mozilla dice esplicitamente che

L'esempio sopra fallirebbe se l'intestazione fosse jolly come: Access-Control-Allow-Origin: *. Poiché Access-Control-Allow-Origin menziona esplicitamente http: //foo.example , il contenuto con cognizione di credenziali viene restituito al contenuto Web invocante.

Di conseguenza non è semplicemente una cattiva pratica usare '*'. Semplicemente non funziona :)


1

Per PHP - questo lavoro per me su Chrome, Safari e Firefox

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

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

usando axios chiama php live services con file: //


Questo funziona anche da parte mia, notare come null sia STRING e non NULL effettivo. Lo uso in quanto header('Access-Control-Allow-Origin: '.( trim($_SERVER['HTTP_REFERER'],'/') ?:'null'),true);consente l'origine incrociata da un server remoto a un altro e cado a (stringa) null per il file locale.
Louis Loudog Trottier,

0

Ho anche avuto lo stesso errore in Chrome (non ho testato altri browser). Era dovuto al fatto che stavo navigando su domain.com anziché su www.domain.com. Un po 'strano, ma ho potuto risolvere il problema aggiungendo le seguenti righe a .htaccess. Reindirizza domain.com a www.domain.com e il problema è stato risolto. Sono un visitatore pigro del web quindi non scrivo quasi mai il www ma a quanto pare in alcuni casi è richiesto.

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

0

Assicurati di utilizzare l'ultima versione di JQuery. Abbiamo riscontrato questo errore per JQuery 1.10.2 e l'errore è stato risolto dopo l'utilizzo di JQuery 1.11.1


0

gente,

Ho riscontrato un problema simile. Ma usando Fiddler, sono stato in grado di risolvere il problema. Il problema è che l'URL del client configurato nell'implementazione CORS sul lato dell'API Web non deve presentare una barra rovesciata finale. Dopo aver inviato la tua richiesta tramite Google Chrome e aver ispezionato la scheda TextView della sezione Headers di Fiddler, il messaggio di errore indica qualcosa del genere:

* "L'origine della politica specificata your_client_url: / 'non è valida. Non può terminare con una barra."

Questo è davvero bizzarro perché ha funzionato senza problemi su Internet Explorer, ma mi ha dato un mal di testa durante i test con Google Chrome.

Ho rimosso la barra nel codice CORS e ricompilato l'API Web e ora l'API è accessibile tramite Chrome e Internet Explorer senza problemi. Per favore, prova questo.

Grazie Andy


0

C'è un piccolo problema nella soluzione pubblicata da CodeGroover sopra , in cui se si modifica un file, è necessario riavviare il server per utilizzare effettivamente il file aggiornato (almeno, nel mio caso).

Quindi, cercando un po ', ho trovato questo Per usare:

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

E poi servirà a http://localhost:8000.


1
Sebbene questo collegamento possa rispondere alla domanda, è meglio includere qui le parti essenziali della risposta e fornire il collegamento come riferimento. Le risposte di solo collegamento possono diventare non valide se la pagina collegata cambia. - Dalla recensione
Vi100,

Chiarito il collegamento.
MiJyn,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.