Partager des ressources multi-origines de manière sécurisée
La règle d'origine commune du navigateur bloque la lecture d'une ressource provenant d'une origine différente. Ce mécanisme empêche les sites malveillants de lire les données d'autres sites, mais il empêche également les utilisations légitimes.
Les applications Web modernes souhaitent souvent obtenir des ressources d'origines différentes, par exemple pour récupérer des données JSON à partir d'un autre domaine ou charger des images à partir d'un autre site dans un élément <canvas>
. Il peut s'agir de ressources publiques accessibles à tous, mais la règle de même origine bloque leur utilisation. Les développeurs ont toujours utilisé des solutions de contournement telles que le JSONP.
Le partage des ressources entre origines multiples (CORS) résout ce problème de manière standardisée. L'activation de CORS permet au serveur d'indiquer au navigateur qu'il peut utiliser une origine supplémentaire.
Comment une demande de ressource fonctionne-t-elle sur le Web ?
![requête et réponse](https://web.developers.google.cn/static/articles/cross-origin-resource-sharing/image/request-response.png?authuser=0000&hl=fr)
Un navigateur et un serveur peuvent échanger des données sur le réseau à l'aide du protocole de transfert hypertexte (HTTP). Le protocole HTTP définit les règles de communication entre le demandeur et le répondant, y compris les informations nécessaires pour obtenir une ressource.
L'en-tête HTTP négocie l'échange de messages entre le client et le serveur, et est utilisé pour déterminer l'accès. La requête du navigateur et le message de réponse du serveur sont divisés en un en-tête et un corps.
En-tête
Informations sur le message, telles que son type ou son encodage. Un en-tête peut inclure différentes informations exprimées sous forme de paires clé/valeur. L'en-tête de requête et l'en-tête de réponse contiennent des informations différentes.
Exemple d'en-tête de requête
Accept: text/html
Cookie: Version=1
Cet en-tête équivaut à dire "Je souhaite recevoir du code HTML en réponse. Voici un biscuit que j'ai. »
Exemple d'en-tête de réponse
Content-Encoding: gzip
Cache-Control: no-store
Cet en-tête équivaut à indiquer "Les données de cette réponse sont encodées avec gzip. Ne le mettez pas en cache."
Corps
Le message lui-même Il peut s'agir de texte brut, d'un binaire d'image, de JSON, HTML ou de nombreux autres formats.
Comment fonctionne CORS ?
La règle d'origine commune indique au navigateur de bloquer les requêtes multi-origines. Lorsque vous avez besoin d'une ressource publique d'une origine différente, le serveur qui fournit les ressources indique au navigateur que l'origine qui envoie la requête peut accéder à sa ressource. Le navigateur le mémorise et autorise le partage multi-origine des ressources pour cette ressource.
Étape 1: requête client (navigateur)
Lorsque le navigateur effectue une requête multi-origine, il ajoute un en-tête Origin
avec l'origine actuelle (schéma, hôte et port).
Étape 2: réponse du serveur
Lorsqu'un serveur voit cet en-tête et souhaite autoriser l'accès, il ajoute à la réponse un en-tête Access-Control-Allow-Origin
spécifiant l'origine de la requête (ou *
pour autoriser n'importe quelle origine).
Étape 3: le navigateur reçoit la réponse
Lorsque le navigateur voit cette réponse avec un en-tête Access-Control-Allow-Origin
approprié, il partage les données de réponse avec le site client.
Partager des identifiants avec CORS
Pour des raisons de confidentialité, CORS est normalement utilisé pour les requêtes anonymes, dans lesquelles le demandeur n'est pas identifié. Si vous souhaitez envoyer des cookies lorsque vous utilisez CORS, qui peut identifier l'expéditeur, vous devez ajouter des en-têtes supplémentaires à la requête et à la réponse.
Requête
Ajoutez credentials: 'include'
aux options de récupération, comme dans l'exemple suivant.
Cela inclut le cookie avec la requête comme suit:
fetch('https://example.com', {
mode: 'cors',
credentials: 'include'
})
Réponse
Access-Control-Allow-Origin
doit être défini sur une origine spécifique (aucun caractère générique utilisant *
) et Access-Control-Allow-Credentials
doit être défini sur true
.
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true
Requêtes préliminaires pour les appels HTTP complexes
Lorsqu'une application Web envoie une requête HTTP complexe, le navigateur ajoute une requête préliminaire au début de la chaîne de requêtes.
La spécification CORS définit une requête complexe comme suit:
- Requête qui utilise des méthodes autres que GET, POST ou HEAD.
- Requête qui inclut des en-têtes autres que
Accept
,Accept-Language
ouContent-Language
. - Une requête ayant un en-tête
Content-Type
autre queapplication/x-www-form-urlencoded
,multipart/form-data
outext/plain
Les navigateurs créent automatiquement toutes les requêtes préliminaires nécessaires et les envoient avant le message de requête réel. La requête préliminaire est une requête OPTIONS
, comme dans l'exemple suivant:
OPTIONS /data HTTP/1.1
Origin: https://example.com
Access-Control-Request-Method: DELETE
Côté serveur, l'application qui reçoit la requête répond à la requête préliminaire avec des informations sur les méthodes acceptées par l'application à partir de cette origine:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, DELETE, HEAD, OPTIONS
La réponse du serveur peut également inclure un en-tête Access-Control-Max-Age
pour spécifier la durée en secondes de mise en cache des résultats préliminaires. Cela permet au client d'envoyer plusieurs requêtes complexes sans avoir à répéter la requête préliminaire.