Condividere risorse cross-origin in sicurezza
Il criterio della stessa origine del browser blocca la lettura di una risorsa da un'altra origine. Questo meccanismo impedisce ai siti dannosi di leggere i dati di altri siti, ma impedisce anche utilizzi legittimi.
Le app web moderne spesso vogliono ottenere risorse da un'origine diversa, ad esempio recuperare dati JSON da un dominio diverso o caricare immagini da un altro sito in un elemento <canvas>
. Possono essere risorse pubbliche che dovrebbero essere disponibili per la lettura da parte di chiunque, ma il criterio della stessa origine ne blocca l'utilizzo. In passato, gli sviluppatori hanno utilizzato soluzioni alternative come
JSONP.
La condivisione delle risorse tra origini (CORS) risolve questo problema in modo standardizzato. L'abilitazione di CORS consente al server di indicare al browser che può utilizzare un'origine aggiuntiva.
Come funziona una richiesta di risorse sul web?
Un browser e un server possono scambiare dati sulla rete utilizzando il Hypertext Transfer Protocol (HTTP). HTTP definisce le regole di comunicazione tra il richiedente e chi risponde, comprese le informazioni necessarie per ottenere una risorsa.
L'intestazione HTTP negozia lo scambio di messaggi tra il client e il server e viene utilizzata per determinare l'accesso. Sia la richiesta del browser sia il messaggio di risposta del server sono suddivisi in un'intestazione e un corpo.
Intestazione
Informazioni sul messaggio, ad esempio il tipo di messaggio o la codifica. Un'intestazione può includere una varietà di informazioni espresse come coppie chiave-valore. L'intestazione della richiesta e l'intestazione della risposta contengono informazioni diverse.
Intestazione della richiesta di esempio
Accept: text/html
Cookie: Version=1
Questa intestazione è equivalente a dire "Voglio ricevere HTML in risposta. Ecco un cookie che ho".
Intestazione di risposta di esempio
Content-Encoding: gzip
Cache-Control: no-store
Questa intestazione è equivalente a dire "I dati in questa risposta sono codificati con gzip. Non memorizzare nella cache."
Corpo
Il messaggio stesso. Può essere testo normale, un'immagine binaria, JSON, HTML o molti altri formati.
Come funziona CORS?
Il criterio della stessa origine indica al browser di bloccare le richieste cross-origin. Quando hai bisogno di una risorsa pubblica da un'origine diversa, il server che fornisce risorse comunica al browser che l'origine che invia la richiesta può accedere alla risorsa. Il browser se ne ricorda e consente la condivisione delle risorse tra origini per quella risorsa.
Passaggio 1: richiesta del client (browser)
Quando il browser effettua una richiesta tra origini, aggiunge un'Origin
intestazione con l'origine corrente (schema, host e porta).
Passaggio 2: risposta del server
Quando un server vede questa intestazione e vuole consentire l'accesso, aggiunge un'intestazione Access-Control-Allow-Origin
alla risposta specificando l'origine della richiesta (o *
per consentire qualsiasi origine).
Passaggio 3: il browser riceve la risposta
Quando il browser vede questa risposta con un'intestazione Access-Control-Allow-Origin
appropriata, condivide i dati della risposta con il sito cliente.
Condividere le credenziali con CORS
Per motivi di privacy, CORS viene normalmente utilizzato per le richieste anonime, in cui il richiedente non è identificato. Se vuoi inviare cookie quando utilizzi CORS, che può identificare il mittente, devi aggiungere ulteriori intestazioni alla richiesta e alla risposta.
Richiesta
Aggiungi credentials: 'include'
alle opzioni di recupero come nell'esempio seguente.
Questo include il cookie con la richiesta come segue:
fetch('https://example.com', {
mode: 'cors',
credentials: 'include'
})
Risposta
Access-Control-Allow-Origin
deve essere impostato su un'origine specifica (nessun carattere jolly che utilizza *
) e Access-Control-Allow-Credentials
deve essere impostato su true
.
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true
Richieste preflight per chiamate HTTP complesse
Quando un'app web effettua una richiesta HTTP complessa, il browser aggiunge una richiesta preflight all'inizio della catena di richieste.
La specifica CORS definisce una richiesta complessa come segue:
- Una richiesta che utilizza metodi diversi da GET, POST o HEAD.
- Una richiesta che include intestazioni diverse da
Accept
,Accept-Language
oContent-Language
. - Una richiesta con un'intestazione
Content-Type
diversa daapplication/x-www-form-urlencoded
,multipart/form-data
otext/plain
.
I browser creano automaticamente le richieste di preflight necessarie e le inviano
prima del messaggio di richiesta effettivo. La richiesta preflight è una richiesta OPTIONS
come nell'esempio seguente:
OPTIONS /data HTTP/1.1
Origin: https://example.com
Access-Control-Request-Method: DELETE
Sul lato server, l'app che riceve la richiesta risponde alla richiesta di preflight con informazioni sui metodi accettati dall'applicazione da questa origine:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, DELETE, HEAD, OPTIONS
La risposta del server può includere anche un'intestazione Access-Control-Max-Age
per
specificare la durata in secondi per memorizzare nella cache i risultati del preflight. In questo modo, il client può inviare più richieste complesse senza dover ripetere la richiesta di preflight.