XMLHttpRequest non può caricare XXX Nessuna intestazione "Access-Control-Allow-Origin"


111

tl; dr; Informazioni sulla politica della stessa origine

Ho un processo Grunt che avvia un'istanza del server express.js. Funzionava perfettamente fino ad ora, quando ha iniziato a pubblicare una pagina vuota con quanto segue che appare nel registro degli errori nella console dello sviluppatore in Chrome (ultima versione):

XMLHttpRequest non può caricare https://www.example.com/ Nessuna intestazione "Access-Control-Allow-Origin" è presente sulla risorsa richiesta. L'accesso all'origine " http: // localhost: 4300 " non è pertanto consentito.

Cosa mi impedisce di accedere alla pagina?


Sto lavorando al sito web e cinque minuti fa andava bene.
Peter David Carter,

1
emette intestazioni CORS? forse se condividessi un codice sarebbe più facile da vedere
Jaromanda X

Plausibile. A quale dipartimento devo chiedere di scoprirlo? Faccio solo la roba backbone.marionette per lo più ...
Peter David Carter,

Si. Suppongo che le organizzazioni dei reparti non siano sempre uniformi comunque, quindi è forse una domanda nebulosa, ma mi piacerebbe conoscere un po 'delle cose di backend / routing / sys-admin nella mia azienda e questa sembrava una buona scusa per familiarizzare io stesso, quindi se ci sono problemi in futuro posso dare una mano.
Peter David Carter,

Chiederei a qualcuno dal lato server all'interno della tua operazione. Devono averlo cambiato su di te se sei stato in grado di accedervi prima.
Larry Lane,

Risposte:


205

tl; dr - C'è un riepilogo alla fine e titoli nella risposta per rendere più facile trovare le parti rilevanti. Si consiglia di leggere tutto, in quanto fornisce uno sfondo utile per comprendere il motivo per cui è più facile vedere come si applica il modo in diverse circostanze.

Informazioni sulla politica della stessa origine

Questa è la politica della stessa origine . È una funzionalità di sicurezza implementata dai browser.

Il tuo caso particolare mostra come è implementato per XMLHttpRequest (e otterrai risultati identici se usassi fetch), ma si applica anche ad altre cose (come immagini caricate su a <canvas>o documenti caricati in un <iframe>), solo con implementazioni leggermente diverse.

(Stranamente, si applica anche ai caratteri CSS, ma questo perché le fonderie fondatrici insistevano sul DRM e non per i problemi di sicurezza che di solito copre la politica della stessa origine).

Lo scenario standard che dimostra la necessità della SOP può essere dimostrato con tre caratteri :

  • Alice è una persona con un browser web
  • Bob gestisce un sito web ( https://www.[website].com/nel tuo esempio)
  • Mallory gestisce un sito web ( http://localhost:4300nel tuo esempio)

Alice ha effettuato l'accesso al sito di Bob e contiene alcuni dati riservati. Forse è una intranet aziendale (accessibile solo ai browser della LAN), o il suo online banking (accessibile solo con un cookie che ottieni dopo aver inserito username e password).

Alice visita il sito Web di Mallory che ha un codice JavaScript che fa sì che il browser di Alice effettui una richiesta HTTP al sito Web di Bob (dal suo indirizzo IP con i suoi cookie, ecc.). Questo potrebbe essere semplice come usare XMLHttpRequeste leggere il file responseText.

La politica della stessa origine del browser impedisce a JavaScript di leggere i dati restituiti dal sito Web di Bob (a cui Bob e Alice non vogliono che Mallory acceda). (Si noti che è possibile, ad esempio, visualizzare un'immagine utilizzando un <img>elemento attraverso le origini, perché il contenuto dell'immagine non è esposta a JavaScript (o Mallory) ... a meno che non si passi tela nel mix, nel qual caso si dovrà generare un same-origin errore di violazione).


Perché la politica della stessa origine si applica quando non pensi che dovrebbe

Per un dato URL è possibile che il SOP non sia necessario. Un paio di scenari comuni in cui questo è il caso sono:

  • Alice, Bob e Mallory sono la stessa persona.
  • Bob sta fornendo informazioni completamente pubbliche

... ma il browser non ha modo di sapere se una delle due precedenti è vera, quindi la fiducia non è automatica e viene applicato il SOP. L'autorizzazione deve essere concessa esplicitamente prima che il browser fornisca i dati forniti a un altro sito web.


Perché la politica della stessa origine si applica solo a JavaScript in una pagina web

Le estensioni del browser *, la scheda Rete negli strumenti di sviluppo del browser e le applicazioni come Postman sono software installati. Non trasmettono dati da un sito Web a JavaScript appartenente a un sito Web diverso solo perché hai visitato quel sito Web diverso . L'installazione del software di solito richiede una scelta più consapevole.

Non esiste una terza parte (Mallory) considerata un rischio.

*Le estensioni del browser devono essere scritte con attenzione per evitare problemi tra le origini. Vedi ad esempio la documentazione di Chrome .


Perché puoi visualizzare i dati nella pagina senza leggerli con JS

Ci sono una serie di circostanze in cui il sito di Mallory può far sì che un browser recuperi dati da una terza parte e li visualizzi (ad esempio aggiungendo un <img>elemento per visualizzare un'immagine). Tuttavia, non è possibile per JavaScript di Mallory leggere i dati in quella risorsa, solo il browser di Alice e il server di Bob possono farlo, quindi è ancora sicuro.


CORS

L' intestazione della rispostaAccess-Control-Allow-Origin HTTP a cui si fa riferimento nel messaggio di errore fa parte dello standard CORS che consente a Bob di concedere esplicitamente l'autorizzazione al sito di Mallory per accedere ai dati tramite il browser di Alice.

Un'implementazione di base includerebbe solo:

Access-Control-Allow-Origin: *

... nelle intestazioni della risposta per consentire a qualsiasi sito Web di leggere i dati.

Access-Control-Allow-Origin: http://example.com/

... consentirebbe solo a un sito specifico di accedervi e Bob può generarlo dinamicamente in base all'intestazione della Origin richiesta per consentire a più siti, ma non a tutti, di accedervi.

Le specifiche di come Bob imposta tale intestazione di risposta dipendono dal server HTTP di Bob e / o dal linguaggio di programmazione lato server. È disponibile una raccolta di guide per varie configurazioni comuni che potrebbero essere utili.

Modello di dove vengono applicate le regole CORS

NB: Alcune richieste sono complesse e inviano una richiesta OPZIONI di preflight a cui il server dovrà rispondere prima che il browser invii il GET / POST / PUT / Qualunque sia la richiesta che il JS vuole fare. Le implementazioni di CORS che si aggiungono solo Access-Control-Allow-Origina URL specifici spesso vengono bloccate da questo.


Ovviamente la concessione dell'autorizzazione tramite CORS è qualcosa che Bob farebbe solo se:

  • I dati non erano privati o
  • Mallory era attendibile

Ma non sono Bob!

Non esiste un meccanismo standard per Mallory per aggiungere questa intestazione perché deve provenire dal sito Web di Bob, che lei non controlla.

Se Bob esegue un'API pubblica, potrebbe esserci un meccanismo per attivare CORS (magari formattando la richiesta in un certo modo o un'opzione di configurazione dopo l'accesso a un sito del portale per sviluppatori per il sito di Bob). Tuttavia, questo dovrà essere un meccanismo implementato da Bob. Mallory potrebbe leggere la documentazione sul sito di Bob per vedere se qualcosa è disponibile, oppure potrebbe parlare con Bob e chiedergli di implementare CORS.


Messaggi di errore che menzionano "Risposta per preflight"

Alcune richieste di origine incrociata sono sottoposte a preflight .

Questo accade quando (grosso modo) provi a fare una richiesta cross-origin che:

  • Include credenziali come i cookie
  • Non può essere generato con un normale modulo HTML (ad es. Ha intestazioni personalizzate o un tipo di contenuto che non è possibile utilizzare in un modulo enctype).

Se stai facendo correttamente qualcosa che necessita di una verifica preliminare

In questi casi, il resto di questa risposta si applica ancora, ma devi anche assicurarti che il server possa ascoltare la richiesta di verifica preliminare (che sarà OPTIONS(e non GET, POSTo qualunque cosa stavi cercando di inviare) e rispondere con il diritto Access-Control-Allow-Originheader ma anche Access-Control-Allow-Methodse Access-Control-Allow-Headersper consentire i tuoi metodi o intestazioni HTTP specifici.

Se stai attivando un preflight per errore

A volte le persone commettono errori quando cercano di costruire richieste Ajax, e talvolta questi fanno scattare la necessità di un preflight. Se l'API è progettata per consentire richieste cross-origin, ma non richiede nulla che necessiti di un preflight, allora questo può interrompere l'accesso.

Gli errori comuni che lo innescano includono:

  • cercando di inserire Access-Control-Allow-Origine altre intestazioni di risposta CORS sulla richiesta. Questi non appartengono alla richiesta, non fanno nulla di utile (quale sarebbe il punto di un sistema di permessi in cui potresti concederti il ​​permesso?), E devono comparire solo sulla risposta.
  • provare a mettere Content-Type: application/jsonun'intestazione su una richiesta GET che non ha un corpo della richiesta per descrivere il contenuto (tipicamente quando l'autore confonde Content-Typee Accept).

In entrambi i casi, la rimozione dell'intestazione della richiesta aggiuntiva sarà spesso sufficiente per evitare la necessità di un preflight (che risolverà il problema quando si comunica con API che supportano richieste semplici ma non richieste preflight).


Risposte opache

A volte è necessario effettuare una richiesta HTTP, ma non è necessario leggere la risposta. ad esempio, se stai inviando un messaggio di log al server per la registrazione.

Se stai utilizzando l' fetchAPI (anziché XMLHttpRequest), puoi configurarla per non provare a utilizzare CORS.

Nota che questo non ti permetterà di fare nulla che richieda a CORS. Non sarai in grado di leggere la risposta. Non sarai in grado di fare una richiesta che richiede un preflight.

Ti consentirà di effettuare una semplice richiesta, non vedere la risposta e non riempire la Console per gli sviluppatori con messaggi di errore.

Come farlo è spiegato dal messaggio di errore di Chrome fornito quando si effettua una richiesta utilizzando fetche non si ottiene l'autorizzazione per visualizzare la risposta con CORS:

L'accesso per il recupero a " https://example.com/dall'origine" https://example.netè stato bloccato dalla politica CORS: nessuna Access-Control-Allow-Originintestazione " " è presente sulla risorsa richiesta. Se una risposta opaca soddisfa le tue esigenze, imposta la modalità della richiesta su "no-cors" per recuperare la risorsa con CORS disabilitato.

Così:

fetch("http://example.com", { mode: "no-cors" });

Alternative a CORS

JSONP

Bob potrebbe anche fornire i dati utilizzando un hack come JSONP, che è il modo in cui le persone eseguivano Ajax cross-origin prima che arrivasse CORS.

Funziona presentando i dati sotto forma di un programma JavaScript che inietta i dati nella pagina di Mallory.

Richiede che Mallory si fidi di Bob per non fornire codice dannoso.

Nota il tema comune: il sito che fornisce i dati deve dire al browser che è OK per un sito di terze parti accedere ai dati che sta inviando al browser.

Poiché JSONP funziona aggiungendo un <script>elemento per caricare i dati sotto forma di un programma JavaScript che chiama una funzione già nella pagina, il tentativo di utilizzare la tecnica JSONP su un URL che restituisce JSON fallirà, in genere con un errore CORB, perché JSON non è JavaScript.

Sposta le due risorse su una singola origine

Se il documento HTML in cui viene eseguito JS e l'URL richiesto sono sulla stessa origine (condividendo lo stesso schema, nome host e porta), la stessa politica di origine concede l'autorizzazione per impostazione predefinita. CORS non è necessario.

Un proxy

Mallory potrebbe utilizzare il codice lato server per recuperare i dati (che potrebbe quindi passare dal suo server al browser di Alice tramite HTTP come al solito).

Può:

  • aggiungi le intestazioni CORS
  • converti la risposta in JSONP
  • esistono sulla stessa origine del documento HTML

Quel codice lato server potrebbe essere scritto e ospitato da una terza parte (come CORS Anywhere). Nota le implicazioni sulla privacy di questo: la terza parte può monitorare chi esegue il proxy cosa attraverso i loro server.

Bob non avrebbe bisogno di concedere alcuna autorizzazione affinché ciò avvenga.

Non ci sono implicazioni per la sicurezza qui dal momento che è solo tra Mallory e Bob. Bob non ha modo di pensare che Mallory sia Alice e di fornire a Mallory dati che dovrebbero essere mantenuti riservati tra Alice e Bob.

Di conseguenza, Mallory può utilizzare questa tecnica solo per leggere dati pubblici .

Tieni presente, tuttavia, che prendere il contenuto dal sito Web di qualcun altro e visualizzarlo da solo potrebbe essere una violazione del copyright e aprirti ad azioni legali.

Scrivere qualcosa di diverso da un'app Web

Come indicato nella sezione "Perché la politica della stessa origine si applica solo a JavaScript in una pagina web", puoi evitare la SOP non scrivendo JavaScript in una pagina web.

Ciò non significa che non puoi continuare a utilizzare JavaScript e HTML, ma puoi distribuirlo utilizzando qualche altro meccanismo, come Node-WebKit o PhoneGap.

Estensioni del browser

È possibile che un'estensione del browser inserisca le intestazioni CORS nella risposta prima che venga applicato il criterio della stessa origine.

Questi possono essere utili per lo sviluppo, ma non sono pratici per un sito di produzione (chiedere a ogni utente del tuo sito di installare un'estensione del browser che disabiliti una funzione di sicurezza del proprio browser è irragionevole).

Inoltre tendono a funzionare solo con richieste semplici (fallendo durante la gestione delle richieste OPZIONI di preflight).

Avere un ambiente di sviluppo adeguato con un server di sviluppo locale è solitamente un approccio migliore.


Altri rischi per la sicurezza

Si noti che SOP / CORS non mitiga gli attacchi XSS , CSRF o SQL Injection che devono essere gestiti in modo indipendente.


Sommario

  • Non c'è niente che puoi fare nel tuo codice lato client che abiliterà l'accesso CORS al server di qualcun altro .
  • Se controlli il server a cui viene effettuata la richiesta: aggiungi le autorizzazioni CORS ad esso.
  • Se sei amichevole con la persona che lo controlla: chiedigli di aggiungere le autorizzazioni CORS ad esso.
  • Se si tratta di un servizio pubblico:
    • Leggi la loro documentazione API per vedere cosa dicono di accedervi con JavaScript lato client:
      • Potrebbero dirti di utilizzare URL specifici
      • Potrebbero supportare JSONP
      • Potrebbero non supportare affatto l'accesso cross-origin dal codice lato client (questa potrebbe essere una decisione deliberata per motivi di sicurezza, soprattutto se devi passare una chiave API personalizzata in ogni richiesta).
    • Assicurati di non attivare una richiesta di verifica preliminare non necessaria. L'API potrebbe concedere l'autorizzazione per richieste semplici ma non per richieste preliminari.
  • Se nessuna delle condizioni precedenti si applica: fai in modo che il browser parli al tuo server, quindi chiedi al tuo server di recuperare i dati dall'altro server e di trasmetterli. (Esistono anche servizi ospitati di terze parti che collegano le intestazioni CORS a risorse accessibili pubblicamente che è possibile utilizzare).

Se eseguo la LAN locale su un server web e provo a caricare ajax dall'IP / URL funzionerà? Non l'ho ancora provato. poiché il mio server web che ritira i dati json sarebbe un MCU
Ciasto piekarz

@Ciastopiekarz - Si applicano regole di origine normale / origine diversa. Si applicano le normali regole di routing di rete.
Quentin

25
La risposta più completa che abbia mai letto, invece di un semplice link su cors ..
pungggi

@Quentin - Wow! +1! Quindi quello che devo capire è che se Alice usa l'estensione CORS, il server pensa che le sue chiamate http non provengano da javascript ma da un'estensione del browser e la tratta come una normale stessa richiesta di origine?
snippetkid

@snippetkid - No. Nel solito caso, il server invierà le intestazioni CORS in ogni risposta e non si preoccuperà della provenienza della richiesta. È responsabilità del browser consentire o negare l'accesso ai dati al JS in base alle intestazioni CORS nella risposta. (Le cose si fanno un po '/ più complesse sul server quando si tratta di richieste di preflight)
Quentin

3

Il server di destinazione deve consentire la richiesta tra le origini. Per consentirlo tramite express, gestisci semplicemente la richiesta delle opzioni http:

app.options('/url...', function(req, res, next){
   res.header('Access-Control-Allow-Origin', "*");
   res.header('Access-Control-Allow-Methods', 'POST');
   res.header("Access-Control-Allow-Headers", "accept, content-type");
   res.header("Access-Control-Max-Age", "1728000");
   return res.sendStatus(200);
});

3

Poiché questo non è menzionato nella risposta accettata.

  • Questo non è il caso di questa domanda esatta, ma potrebbe aiutare gli altri che cercano quel problema
  • Questo è qualcosa che puoi fare nel tuo codice client per prevenire errori CORS in alcuni casi .

Puoi fare uso di Richieste semplici .
Per eseguire una "Richiesta semplice", la richiesta deve soddisfare diverse condizioni. Ad esempio consentendo solo POST, GETe HEADil metodo, nonché consentendo solo un dato intestazioni (è possibile trovare tutte le condizioni qui ).

Se il codice client non imposta esplicitamente le intestazioni interessate (ad es. "Accetta") con un valore fisso nella richiesta, potrebbe accadere che alcuni client impostino automaticamente queste intestazioni con alcuni valori "non standard" facendo sì che il server non le accetti come Richiesta semplice: che ti darà un errore CORS.


2

Ciò sta accadendo a causa dell'errore CORS. CORS sta per Cross Origin Resource Sharing. In parole semplici, questo errore si verifica quando proviamo ad accedere a un dominio / risorsa da un altro dominio.

Per saperne di più qui: errore CORS con jquery

Per risolvere questo problema, se hai accesso all'altro dominio, dovrai consentire Access-Control-Allow-Origin nel server. Questo può essere aggiunto nelle intestazioni. Puoi abilitarlo per tutte le richieste / domini o per un dominio specifico.

Come far funzionare una richiesta post di condivisione delle risorse tra le origini (CORS)

Questi collegamenti possono aiutare


0

Questo problema CORS non è stato ulteriormente elaborato (per altre cause).

Sto riscontrando questo problema attualmente per motivi diversi. Anche il mio front-end restituisce l'errore di intestazione "Access-Control-Allow-Origin".

Solo che ho indicato l'URL sbagliato in modo che questa intestazione non fosse riflessa correttamente (in cui continuavo a presumere che lo facesse). localhost (front-end) -> chiamata a http non protetto (dovrebbe essere https), assicurati che l'endpoint API dal front-end punti al protocollo corretto.


0

Ho ricevuto lo stesso errore nella console Chrome.

Il mio problema era che stavo cercando di accedere al sito utilizzando http://invece di https://. Quindi non c'era nulla da riparare, dovevo solo andare sullo stesso sito usando https.


-1

La richiesta "Ottieni" con l'aggiunta di intestazioni si trasforma in una richiesta "Opzioni". Quindi si verificano problemi con la politica di Cors. Devi implementare la richiesta "Opzioni" al tuo server.


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.