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:4300
nel 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 XMLHttpRequest
e 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.
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-Origin
a 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
, POST
o qualunque cosa stavi cercando di inviare) e rispondere con il diritto Access-Control-Allow-Origin
header ma anche Access-Control-Allow-Methods
e Access-Control-Allow-Headers
per 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-Origin
e 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/json
un'intestazione su una richiesta GET che non ha un corpo della richiesta per descrivere il contenuto (tipicamente quando l'autore confonde Content-Type
e 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' fetch
API (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 fetch
e 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-Origin
intestazione " " è 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).