Partager des ressources entre origines multiples de manière sécurisée
Les règles de même origine du navigateur empêchent la lecture d'une ressource provenant d'une autre origine. 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'une autre origine, par
exemple en récupérant des données JSON à partir d'un autre domaine ou en chargeant des images d'un
autre site dans un <canvas> élément. Il peut s'agir de ressources publiques qui devraient être accessibles à tous, mais les règles de même origine bloquent leur utilisation. Les développeurs ont toujours utilisé des solutions de contournement telles que
JSONP.
Le Cross-Origin Resource Sharing (CORS) résout ce problème de manière standardisée. L'activation du CORS permet au serveur d'indiquer au navigateur qu'il peut utiliser une origine supplémentaire.
Comment fonctionne une requête de ressource sur le Web ?
Un navigateur et un serveur peuvent échanger des données sur le réseau à l'aide du protocole HTTP (Hypertext Transfer Protocol). Le protocole HTTP définit les règles de communication entre le demandeur et le répondeur, 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 le type ou l'encodage du message. Un en-tête peut inclure diverses 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 cookie que j'ai."
Exemple d'en-tête de réponse
Content-Encoding: gzip
Cache-Control: no-store
Cet en-tête équivaut à dire "Les données de cette réponse sont encodées avec gzip. Ne mettez pas cela en cache."
Body
Le message lui-même. Il peut s'agir de texte brut, d'un binaire d'image, de JSON, de HTML ou de nombreux autres formats.
Comment fonctionne le CORS ?
Les règles de même origine indiquent au navigateur de bloquer les requêtes d'origines multiples. Lorsque vous avez besoin d'une ressource publique provenant d'une autre origine, le serveur fournissant la ressource indique au navigateur que l'origine qui envoie la requête peut accéder à sa ressource. Le navigateur s'en souvient et autorise le partage des ressources entre origines multiples pour cette ressource.
Étape 1 : Requête du client (navigateur)
Lorsque le navigateur effectue une requête multi-origines, 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 un en-tête Access-Control-Allow-Origin à la réponse en 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 le CORS
Pour des raisons de confidentialité, le 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 le CORS, ce 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 n'est utilisé avec *), 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 effectue 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 :
- Une requête qui utilise des méthodes autres que GET, POST ou HEAD.
- Une requête qui inclut des en-têtes autres que
Accept,Accept-LanguageouContent-Language. - Une requête dont l'en-tête
Content-Typeest différent deapplication/x-www-form-urlencoded,multipart/form-dataoutext/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 que l'application accepte 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 pendant laquelle les résultats des requêtes préliminaires doivent être mis en cache. Cela permet au client d'envoyer plusieurs requêtes complexes sans avoir à répéter la requête préliminaire.