Percez les secrets de CORS (Cross-Origin Resource Sharing) et apprenez Ă activer en toute sĂ©curitĂ© les requĂȘtes inter-domaines dans vos applications web. Ce guide complet couvre les bases jusqu'aux configurations avancĂ©es, assurant une communication fluide et sĂ©curisĂ©e entre les diffĂ©rentes origines.
Démystifier CORS : Un guide complet sur le partage des ressources entre origines multiples
Dans le web interconnectĂ© d'aujourd'hui, les applications ont souvent besoin d'accĂ©der Ă des ressources provenant de diffĂ©rentes origines. C'est lĂ que le Partage des ressources entre origines multiples (CORS) entre en jeu. CORS est un mĂ©canisme de sĂ©curitĂ© crucial qui rĂ©git la maniĂšre dont les navigateurs web gĂšrent les requĂȘtes d'une origine (domaine, protocole et port) vers une origine diffĂ©rente. Comprendre CORS est essentiel pour tout dĂ©veloppeur web afin de construire des applications web sĂ©curisĂ©es et fonctionnelles.
Qu'est-ce que la politique de mĂȘme origine (Same-Origin Policy) ?
Avant de plonger dans CORS, il est important de comprendre la politique de mĂȘme origine (Same-Origin Policy - SOP). La SOP est un mĂ©canisme de sĂ©curitĂ© fondamental implĂ©mentĂ© dans les navigateurs web. Son but est d'empĂȘcher les scripts malveillants d'un site web d'accĂ©der Ă des donnĂ©es sensibles sur un autre site web. Une origine est dĂ©finie par la combinaison du protocole (par ex., HTTP ou HTTPS), du domaine (par ex., example.com) et du numĂ©ro de port (par ex., 80 ou 443). Deux URL sont considĂ©rĂ©es comme ayant la mĂȘme origine si elles partagent le mĂȘme protocole, le mĂȘme domaine et le mĂȘme port.
Exemple :
http://example.com/app1ethttp://example.com/app2- MĂȘme origine (mĂȘme protocole, domaine et port)https://example.com/app1ethttp://example.com/app1- Origine diffĂ©rente (protocole diffĂ©rent)http://example.com:8080/app1ethttp://example.com/app1- Origine diffĂ©rente (port diffĂ©rent)http://sub.example.com/app1ethttp://example.com/app1- Origine diffĂ©rente (sous-domaine diffĂ©rent â considĂ©rĂ© comme un domaine diffĂ©rent)
La SOP empĂȘche les scripts d'accĂ©der Ă des ressources d'une origine diffĂ©rente, Ă moins que des mesures spĂ©cifiques, telles que CORS, ne soient en place pour l'autoriser.
Pourquoi CORS est-il nécessaire ?
Bien que la politique de mĂȘme origine soit vitale pour la sĂ©curitĂ©, elle peut aussi ĂȘtre restrictive. De nombreuses applications web modernes dĂ©pendent de la rĂ©cupĂ©ration de donnĂ©es depuis des serveurs diffĂ©rents, comme des API ou des rĂ©seaux de diffusion de contenu (CDN). CORS offre un moyen contrĂŽlĂ© d'assouplir la SOP et d'autoriser les requĂȘtes lĂ©gitimes entre origines multiples tout en maintenant la sĂ©curitĂ©.
Imaginez un scĂ©nario oĂč une application web hĂ©bergĂ©e sur http://example.com a besoin de rĂ©cupĂ©rer des donnĂ©es d'un serveur d'API hĂ©bergĂ© sur http://api.example.net. Sans CORS, le navigateur bloquerait cette requĂȘte Ă cause de la SOP. CORS permet au serveur d'API de spĂ©cifier explicitement quelles origines sont autorisĂ©es Ă accĂ©der Ă ses ressources, permettant ainsi Ă l'application web de fonctionner correctement.
Comment fonctionne CORS : Les bases
CORS fonctionne grĂące Ă une sĂ©rie d'en-tĂȘtes HTTP Ă©changĂ©s entre le client (navigateur) et le serveur. Le serveur utilise ces en-tĂȘtes pour informer le navigateur s'il est autorisĂ© Ă accĂ©der Ă la ressource demandĂ©e. L'en-tĂȘte HTTP clĂ© impliquĂ© est Access-Control-Allow-Origin.
ScĂ©nario 1 : RequĂȘte simple
Une « requĂȘte simple » est une requĂȘte GET, HEAD ou POST qui remplit des critĂšres spĂ©cifiques (par ex., l'en-tĂȘte Content-Type est l'un des suivants : application/x-www-form-urlencoded, multipart/form-data, ou text/plain). Dans ce cas, le navigateur envoie la requĂȘte directement au serveur, et le serveur rĂ©pond avec l'en-tĂȘte Access-Control-Allow-Origin.
RequĂȘte du client (depuis http://example.com) :
GET /data HTTP/1.1
Host: api.example.net
Origin: http://example.com
Réponse du serveur (depuis http://api.example.net) :
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Content-Type: application/json
{
"data": "Quelques données du serveur"
}
Dans cet exemple, le serveur rĂ©pond avec Access-Control-Allow-Origin: http://example.com, indiquant que les requĂȘtes provenant de http://example.com sont autorisĂ©es. Si l'origine dans la requĂȘte ne correspond pas Ă la valeur de l'en-tĂȘte Access-Control-Allow-Origin (ou si l'en-tĂȘte est absent), le navigateur bloquera la rĂ©ponse et empĂȘchera le script cĂŽtĂ© client d'accĂ©der aux donnĂ©es.
ScĂ©nario 2 : RequĂȘte preflight (pour les requĂȘtes complexes)
Pour les requĂȘtes plus complexes, telles que celles utilisant des mĂ©thodes HTTP comme PUT, DELETE, ou celles avec des en-tĂȘtes personnalisĂ©s, le navigateur effectue une requĂȘte « preflight » en utilisant la mĂ©thode HTTP OPTIONS. Cette requĂȘte preflight demande la permission au serveur avant d'envoyer la requĂȘte rĂ©elle. Le serveur rĂ©pond avec des en-tĂȘtes qui spĂ©cifient quelles mĂ©thodes, quels en-tĂȘtes et quelles origines sont autorisĂ©s.
RequĂȘte preflight du client (depuis http://example.com) :
OPTIONS /data HTTP/1.1
Host: api.example.net
Origin: http://example.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
Réponse du serveur (depuis http://api.example.net) :
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Access-Control-Allow-Methods: GET, PUT, DELETE
Access-Control-Allow-Headers: X-Custom-Header, Content-Type
Access-Control-Max-Age: 3600
Explication des en-tĂȘtes :
Access-Control-Allow-Origin: http://example.com- Indique que les requĂȘtes depuishttp://example.comsont autorisĂ©es.Access-Control-Allow-Methods: GET, PUT, DELETE- SpĂ©cifie les mĂ©thodes HTTP autorisĂ©es pour les requĂȘtes inter-origines.Access-Control-Allow-Headers: X-Custom-Header, Content-Type- Liste les en-tĂȘtes personnalisĂ©s autorisĂ©s dans la requĂȘte rĂ©elle.Access-Control-Max-Age: 3600- SpĂ©cifie la durĂ©e (en secondes) pendant laquelle la rĂ©ponse preflight peut ĂȘtre mise en cache par le navigateur. Cela aide Ă rĂ©duire le nombre de requĂȘtes preflight.
Si la rĂ©ponse preflight du serveur indique que la requĂȘte est autorisĂ©e, le navigateur procĂšde Ă la requĂȘte rĂ©elle. Sinon, le navigateur bloque la requĂȘte.
RequĂȘte rĂ©elle du client (depuis http://example.com) :
PUT /data HTTP/1.1
Host: api.example.net
Origin: http://example.com
X-Custom-Header: some-value
Content-Type: application/json
{
"data": "Quelques données à mettre à jour"
}
Réponse du serveur (depuis http://api.example.net) :
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Content-Type: application/json
{
"status": "Données mises à jour avec succÚs"
}
En-tĂȘtes CORS courants
Voici une description des principaux en-tĂȘtes CORS que vous devez comprendre :
Access-Control-Allow-Origin: Cet en-tĂȘte est le plus fondamental. Il spĂ©cifie la ou les origines autorisĂ©es Ă accĂ©der Ă la ressource. Les valeurs possibles incluent :- Une origine spĂ©cifique (par ex.,
http://example.com). *(joker) : Cela autorise les requĂȘtes de n'importe quelle origine. Ă utiliser avec prudence, car cela peut compromettre la sĂ©curitĂ© si des donnĂ©es sensibles sont impliquĂ©es. Il faut gĂ©nĂ©ralement l'Ă©viter dans les environnements de production.
- Une origine spécifique (par ex.,
Access-Control-Allow-Methods: Cet en-tĂȘte spĂ©cifie les mĂ©thodes HTTP (par ex., GET, POST, PUT, DELETE) qui sont autorisĂ©es pour les requĂȘtes inter-origines. Il est utilisĂ© dans la rĂ©ponse preflight.Access-Control-Allow-Headers: Cet en-tĂȘte liste les en-tĂȘtes personnalisĂ©s qui sont autorisĂ©s dans les requĂȘtes inter-origines. Il est Ă©galement utilisĂ© dans la rĂ©ponse preflight.Access-Control-Allow-Credentials: Cet en-tĂȘte indique si le serveur autorise l'inclusion d'informations d'identification (par ex., cookies, en-tĂȘtes d'autorisation) dans les requĂȘtes inter-origines. Il doit ĂȘtre dĂ©fini surtruesi vous avez besoin d'envoyer des informations d'identification. CĂŽtĂ© client, vous devez Ă©galement dĂ©finirwithCredentials = truesur l'objet XMLHttpRequest.Access-Control-Expose-Headers: Par dĂ©faut, les navigateurs n'exposent qu'un ensemble limitĂ© d'en-tĂȘtes de rĂ©ponse (par ex.,Cache-Control,Content-Language,Content-Type,Expires,Last-Modified,Pragma) aux scripts cĂŽtĂ© client. Si vous souhaitez exposer d'autres en-tĂȘtes, vous devez les lister dans l'en-tĂȘteAccess-Control-Expose-Headers.Access-Control-Max-Age: Cet en-tĂȘte spĂ©cifie la durĂ©e maximale (en secondes) pendant laquelle un navigateur peut mettre en cache la requĂȘte preflight. Une valeur plus longue rĂ©duit le nombre de requĂȘtes preflight, amĂ©liorant ainsi les performances.
CORS dans différents langages cÎté serveur
La mise en Ćuvre de CORS implique gĂ©nĂ©ralement de configurer votre application cĂŽtĂ© serveur pour qu'elle envoie les en-tĂȘtes CORS appropriĂ©s. Voici des exemples de la maniĂšre de le faire dans divers langages et frameworks :
Node.js avec Express
Vous pouvez utiliser le package middleware cors :
const express = require('express');
const cors = require('cors');
const app = express();
// Activer CORS pour toutes les origines (Ă UTILISER AVEC PRUDENCE EN PRODUCTION)
app.use(cors());
// Alternativement, configurer CORS pour des origines spécifiques
// app.use(cors({
// origin: 'http://example.com'
// }));
app.get('/data', (req, res) => {
res.json({ message: 'Ceci est activé par CORS pour toutes les origines !' });
});
app.listen(3000, () => {
console.log('Le serveur tourne sur le port 3000');
});
Python avec Flask
Vous pouvez utiliser l'extension Flask-CORS :
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
# Alternativement, configurer CORS pour des origines spécifiques
# CORS(app, resources={r"/api/*": {"origins": "http://example.com"}})
@app.route("/data")
def hello():
return {"message": "Ceci est activé par CORS pour toutes les origines !"}
if __name__ == '__main__':
app.run(debug=True)
Java avec Spring Boot
Vous pouvez configurer CORS dans votre application Spring Boot en utilisant des annotations ou des classes de configuration :
Utilisation d'annotations :
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@CrossOrigin(origins = "http://example.com") // Autoriser les requĂȘtes depuis http://example.com
public class DataController {
@GetMapping("/data")
public String getData() {
return "Ceci est activé par CORS pour http://example.com !";
}
}
Utilisation de la configuration :
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/data")
.allowedOrigins("http://example.com") // Autoriser les requĂȘtes depuis http://example.com
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*");
}
}
PHP
"Ceci est activé par CORS pour http://example.com !");
echo json_encode($data);
?>
CORS et considérations de sécurité
Bien que CORS permette les requĂȘtes inter-origines, il est crucial de le mettre en Ćuvre de maniĂšre sĂ©curisĂ©e. Voici quelques considĂ©rations importantes :
- Ăvitez d'utiliser
*pourAccess-Control-Allow-Originen production : Cela autorise les requĂȘtes de n'importe quelle origine, ce qui peut constituer un risque de sĂ©curitĂ©. SpĂ©cifiez plutĂŽt explicitement les origines qui sont autorisĂ©es Ă accĂ©der Ă vos ressources. - Validez l'en-tĂȘte
OrigincĂŽtĂ© serveur : MĂȘme si vous utilisez un framework qui gĂšre la configuration CORS, il est de bonne pratique de valider l'en-tĂȘteOrigincĂŽtĂ© serveur pour s'assurer que la requĂȘte provient d'une origine attendue. - Soyez attentif Ă
Access-Control-Allow-Credentials: Si vous utilisez des informations d'identification (par ex., cookies, en-tĂȘtes d'autorisation), assurez-vous de dĂ©finirAccess-Control-Allow-Credentials: truecĂŽtĂ© serveur etwithCredentials = truecĂŽtĂ© client. Cependant, sachez que l'utilisation deAccess-Control-Allow-Origin: *n'est pas autorisĂ©e lorsqueAccess-Control-Allow-Credentialsest dĂ©fini surtrue. Vous devez spĂ©cifier explicitement les origines autorisĂ©es. - Configurez correctement
Access-Control-Allow-MethodsetAccess-Control-Allow-Headers: N'autorisez que les mĂ©thodes HTTP et les en-tĂȘtes nĂ©cessaires au bon fonctionnement de votre application. Cela aide Ă rĂ©duire la surface d'attaque. - Utilisez HTTPS : Utilisez toujours HTTPS pour vos applications web et vos API afin de protĂ©ger les donnĂ©es en transit.
Dépannage des problÚmes CORS
Les problĂšmes CORS peuvent ĂȘtre frustrants Ă dĂ©boguer. Voici quelques problĂšmes courants et comment les rĂ©soudre :
- « Aucun en-tĂȘte 'Access-Control-Allow-Origin' n'est prĂ©sent sur la ressource demandĂ©e » : C'est l'erreur CORS la plus courante. Cela signifie que le serveur n'envoie pas l'en-tĂȘte
Access-Control-Allow-Origindans sa rĂ©ponse. VĂ©rifiez attentivement votre configuration cĂŽtĂ© serveur pour vous assurer que l'en-tĂȘte est envoyĂ© correctement. - « La rĂ©ponse Ă la requĂȘte preflight ne passe pas le contrĂŽle d'accĂšs : elle n'a pas le statut HTTP ok » : Cette erreur indique que la requĂȘte preflight a Ă©chouĂ©. Cela peut se produire si le serveur n'est pas configurĂ© pour gĂ©rer les requĂȘtes OPTIONS ou si les en-tĂȘtes
Access-Control-Allow-MethodsouAccess-Control-Allow-Headersne sont pas configurĂ©s correctly. - « La valeur de l'en-tĂȘte 'Access-Control-Allow-Origin' dans la rĂ©ponse n'est pas Ă©gale Ă l'origine de la requĂȘte » : Cette erreur signifie que l'origine de la requĂȘte ne correspond pas Ă la valeur de l'en-tĂȘte
Access-Control-Allow-Origin. Assurez-vous que le serveur envoie la bonne origine dans la rĂ©ponse. - Mise en cache du navigateur : Parfois, les navigateurs peuvent mettre en cache les rĂ©ponses CORS, ce qui peut entraĂźner un comportement inattendu. Essayez de vider le cache de votre navigateur ou d'utiliser un autre navigateur pour voir si cela rĂ©sout le problĂšme. Vous pouvez Ă©galement utiliser l'en-tĂȘte
Access-Control-Max-Agepour contrÎler la durée de mise en cache de la réponse preflight par le navigateur.
Outils de débogage :
- Outils de dĂ©veloppement du navigateur : Utilisez les outils de dĂ©veloppement du navigateur (gĂ©nĂ©ralement accessibles en appuyant sur F12) pour inspecter les requĂȘtes et rĂ©ponses rĂ©seau. Recherchez les en-tĂȘtes et les messages d'erreur liĂ©s Ă CORS.
- VĂ©rificateurs CORS en ligne : Il existe des outils en ligne qui peuvent vous aider Ă tester votre configuration CORS. Ces outils envoient une requĂȘte Ă votre serveur et analysent les en-tĂȘtes de rĂ©ponse pour identifier les problĂšmes potentiels.
Scénarios CORS avancés
Bien que les concepts de base de CORS soient relativement simples, il existe des scénarios plus avancés à prendre en compte :
- CORS avec des sous-domaines : Si vous devez autoriser les requĂȘtes de plusieurs sous-domaines (par ex.,
app1.example.com,app2.example.com), vous ne pouvez pas simplement utiliser un joker comme*.example.comdans l'en-tĂȘteAccess-Control-Allow-Origin. Au lieu de cela, vous devrez gĂ©nĂ©rer dynamiquement l'en-tĂȘteAccess-Control-Allow-Originen fonction de l'en-tĂȘteOriginde la requĂȘte. N'oubliez pas de valider l'origine par rapport Ă une liste blanche de sous-domaines autorisĂ©s pour Ă©viter les vulnĂ©rabilitĂ©s de sĂ©curitĂ©. - CORS avec plusieurs origines : Si vous devez autoriser les requĂȘtes de plusieurs origines spĂ©cifiques, vous ne pouvez pas spĂ©cifier plusieurs origines dans l'en-tĂȘte
Access-Control-Allow-Origin(par ex.,Access-Control-Allow-Origin: http://example.com, http://another.comest invalide). Au lieu de cela, vous devrez gĂ©nĂ©rer dynamiquement l'en-tĂȘteAccess-Control-Allow-Originen fonction de l'en-tĂȘteOriginde la requĂȘte. - CORS et les CDN : Lorsque vous utilisez un CDN pour servir votre API, vous devez configurer le CDN pour qu'il transmette l'en-tĂȘte
OriginĂ votre serveur d'origine et pour qu'il mette en cache correctement l'en-tĂȘteAccess-Control-Allow-Origin. Consultez la documentation de votre fournisseur de CDN pour des instructions spĂ©cifiques.
Bonnes pratiques CORS
Pour garantir une mise en Ćuvre sĂ©curisĂ©e et efficace de CORS, suivez ces bonnes pratiques :
- Principe du moindre privilĂšge : N'autorisez que l'ensemble minimal d'origines, de mĂ©thodes et d'en-tĂȘtes nĂ©cessaires au bon fonctionnement de votre application.
- Examinez réguliÚrement la configuration CORS : Au fur et à mesure que votre application évolue, examinez réguliÚrement votre configuration CORS pour vous assurer qu'elle est toujours appropriée et sécurisée.
- Utilisez un framework ou une bibliothĂšque : Tirez parti des frameworks ou des bibliothĂšques existants qui offrent un support CORS intĂ©grĂ©. Cela peut simplifier la mise en Ćuvre et rĂ©duire le risque d'erreurs.
- Surveillez les violations de CORS : Mettez en place une surveillance pour détecter et répondre aux violations potentielles de CORS.
- Restez à jour : Tenez-vous au courant des derniÚres spécifications et recommandations de sécurité de CORS.
Conclusion
CORS est un mĂ©canisme de sĂ©curitĂ© essentiel qui permet des requĂȘtes contrĂŽlĂ©es entre origines multiples dans les applications web. Comprendre le fonctionnement de CORS et savoir comment le configurer correctement est essentiel pour tout dĂ©veloppeur web. En suivant les directives et les bonnes pratiques dĂ©crites dans ce guide complet, vous pouvez construire des applications web sĂ©curisĂ©es et fonctionnelles qui interagissent de maniĂšre transparente avec des ressources de diffĂ©rentes origines.
N'oubliez pas de toujours donner la priorité à la sécurité et d'éviter d'utiliser des configurations CORS trop permissives. En examinant attentivement les implications de sécurité de vos paramÚtres CORS, vous pouvez protéger vos applications et vos données contre les accÚs non autorisés.
Nous espérons que ce guide vous a aidé à démystifier CORS. Bon codage !