tl; dr - Il y a un résumé à la fin et des titres dans la réponse pour faciliter la recherche des parties pertinentes. Il est cependant recommandé de tout lire, car il fournit des informations utiles pour comprendre le pourquoi, cela permet de voir plus facilement comment le comment s'applique dans différentes circonstances.
À propos de la politique de même origine
C'est la même politique d'origine . C'est une fonction de sécurité mise en œuvre par les navigateurs.
Votre cas particulier montre comment il est implémenté pour XMLHttpRequest (et vous obtiendrez des résultats identiques si vous utilisiez fetch), mais cela s'applique également à d'autres choses (comme les images chargées sur un <canvas>
ou les documents chargés dans un <iframe>
), juste avec implémentations légèrement différentes.
(Bizarrement, cela s'applique également aux polices CSS, mais c'est parce que les fonderies ont insisté sur le DRM et non pour les problèmes de sécurité que la politique de même origine couvre généralement).
Le scénario standard qui démontre la nécessité de la SOP peut être démontré avec trois caractères :
- Alice est une personne avec un navigateur Web
- Bob dirige un site Web (
https://www.[website].com/
dans votre exemple)
- Mallory gère un site Web (
http://localhost:4300
dans votre exemple)
Alice est connectée au site de Bob et y possède des données confidentielles. Il s'agit peut-être d'un intranet d'entreprise (accessible uniquement aux navigateurs sur le LAN), ou de sa banque en ligne (accessible uniquement avec un cookie que vous obtenez après la saisie d'un nom d'utilisateur et d'un mot de passe).
Alice visite le site Web de Mallory qui contient du JavaScript qui oblige le navigateur d'Alice à faire une requête HTTP au site Web de Bob (à partir de son adresse IP avec ses cookies, etc.). Cela peut être aussi simple que d'utiliser XMLHttpRequest
et de lire le fichier responseText
.
La politique de même origine du navigateur empêche JavaScript de lire les données renvoyées par le site Web de Bob (auquel Bob et Alice ne veulent pas que Mallory accède). (Notez que vous pouvez, par exemple, afficher une image en utilisant un <img>
élément à travers origines parce que le contenu de l'image ne soit pas exposée à JavaScript (ou Mallory) ... à moins que vous jetez la toile dans le mélange dans ce cas , vous allez générer une même origine erreur de violation).
Pourquoi la politique de même origine s'applique alors que vous ne pensez pas qu'elle devrait
Pour une URL donnée, il est possible que le SOP ne soit pas nécessaire. Voici quelques scénarios courants où c'est le cas:
- Alice, Bob et Mallory sont la même personne.
- Bob fournit des informations entièrement publiques
… Mais le navigateur n'a aucun moyen de savoir si l'une ou l'autre des conditions ci-dessus est vraie, donc la confiance n'est pas automatique et la SOP est appliquée. L'autorisation doit être accordée explicitement avant que le navigateur ne communique les données qui lui ont été fournies à un autre site Web.
Pourquoi la politique de même origine s'applique uniquement à JavaScript dans une page Web
Les extensions de navigateur *
, l'onglet Réseau dans les outils de développement de navigateur et les applications comme Postman sont des logiciels installés. Ils ne transmettent pas les données d'un site Web au JavaScript appartenant à un autre site Web simplement parce que vous avez visité ce site Web différent . L'installation d'un logiciel prend généralement un choix plus conscient.
Il n'y a pas de tiers (Mallory) qui soit considéré comme un risque.
*
Les extensions de navigateur doivent être écrites avec soin pour éviter les problèmes d'origine croisée. Consultez la documentation Chrome par exemple .
Pourquoi vous pouvez afficher des données dans la page sans la lire avec JS
Il existe un certain nombre de circonstances dans lesquelles le site de Mallory peut amener un navigateur à extraire des données d'un tiers et à les afficher (par exemple en ajoutant un <img>
élément pour afficher une image). Il n'est pas possible pour le JavaScript de Mallory de lire les données de cette ressource, seuls le navigateur d'Alice et le serveur de Bob peuvent le faire, il est donc toujours sécurisé.
CORS
L' Access-Control-Allow-Origin
en- tête de réponse HTTP mentionné dans le message d'erreur fait partie de la norme CORS qui permet à Bob d'accorder explicitement l'autorisation au site de Mallory d'accéder aux données via le navigateur d'Alice.
Une implémentation de base comprendrait simplement:
Access-Control-Allow-Origin: *
… Dans les en-têtes de réponse pour permettre à tout site Web de lire les données.
Access-Control-Allow-Origin: http://example.com/
… Permettrait seulement à un site spécifique d'y accéder, et Bob peut générer dynamiquement cela en fonction de l'en- tête de la Origin
requête pour permettre à plusieurs sites, mais pas à tous, d'y accéder.
Les spécificités de la façon dont Bob définit cet en-tête de réponse dépendent du serveur HTTP de Bob et / ou du langage de programmation côté serveur. Il existe une collection de guides pour diverses configurations courantes qui pourraient vous aider.
NB: Certaines requêtes sont complexes et envoient une requête OPTIONS avant le vol à laquelle le serveur devra répondre avant que le navigateur envoie la requête GET / POST / PUT / Quelle que soit la requête que le JS souhaite faire. Les implémentations de CORS qui ne s'ajoutent Access-Control-Allow-Origin
qu'à des URL spécifiques sont souvent déclenchées par cela.
De toute évidence, accorder l'autorisation via CORS est quelque chose que Bob ne ferait que si:
- Les données n'étaient pas privées ou
- Mallory avait confiance
Mais je ne suis pas Bob!
Il n'y a pas de mécanisme standard permettant à Mallory d'ajouter cet en-tête car il doit provenir du site Web de Bob, qu'elle ne contrôle pas.
Si Bob exécute une API publique, il peut y avoir un mécanisme pour activer CORS (peut-être en formatant la demande d'une certaine manière, ou une option de configuration après la connexion à un site de portail de développeur pour le site de Bob). Cela devra cependant être un mécanisme mis en œuvre par Bob. Mallory pourrait lire la documentation sur le site de Bob pour voir si quelque chose est disponible, ou elle pourrait parler à Bob et lui demander d'implémenter CORS.
Messages d'erreur qui mentionnent "Réponse pour le contrôle en amont"
Certaines demandes d'origine croisée sont contrôlées en amont .
Cela se produit lorsque (grosso modo) vous essayez de faire une demande d'origine croisée qui:
- Comprend des informations d'identification comme les cookies
- N'a pas pu être généré avec un formulaire HTML normal (par exemple, il a des en-têtes personnalisés ou un type de contenu que vous ne pouvez pas utiliser dans un formulaire
enctype
).
Si vous faites correctement quelque chose qui nécessite un contrôle en amont
Dans ces cas, le reste de cette réponse s'applique toujours, mais vous devez également vous assurer que le serveur peut écouter la demande de contrôle en amont (qui sera OPTIONS
(et non GET
, POST
ou ce que vous essayiez d'envoyer) et y répondre avec le droit Access-Control-Allow-Origin
header mais aussi Access-Control-Allow-Methods
et Access-Control-Allow-Headers
pour autoriser vos méthodes ou en-têtes HTTP spécifiques.
Si vous déclenchez un contrôle en amont par erreur
Parfois, les gens font des erreurs en essayant de construire des requêtes Ajax, et parfois cela déclenche le besoin d'un contrôle en amont. Si l'API est conçue pour autoriser les requêtes d'origine croisée, mais ne nécessite rien qui nécessiterait un contrôle en amont, cela peut interrompre l'accès.
Les erreurs courantes qui déclenchent cela incluent:
- essayer de mettre
Access-Control-Allow-Origin
et d'autres en-têtes de réponse CORS sur la demande. Celles-ci n'appartiennent pas à la demande, ne font rien d'utile (quel serait l'intérêt d'un système d'autorisations où vous pourriez vous accorder la permission?), Et doivent apparaître uniquement sur la réponse.
- essayer de mettre un en-
Content-Type: application/json
tête sur une requête GET qui n'a pas de corps de requête pour décrire le contenu de (généralement lorsque l'auteur confond Content-Type
et Accept
).
Dans l'un ou l'autre de ces cas, la suppression de l'en-tête de demande supplémentaire sera souvent suffisante pour éviter le besoin d'un contrôle en amont (ce qui résoudra le problème lors de la communication avec des API qui prennent en charge des requêtes simples mais pas des requêtes contrôlées en amont).
Réponses opaques
Parfois, vous devez faire une requête HTTP, mais vous n'avez pas besoin de lire la réponse. par exemple, si vous publiez un message de journal sur le serveur pour enregistrement.
Si vous utilisez l' fetch
API (plutôt que XMLHttpRequest
), vous pouvez la configurer pour ne pas essayer d'utiliser CORS.
Notez que cela ne vous permettra pas de faire quoi que ce soit que vous exigez de CORS. Vous ne pourrez pas lire la réponse. Vous ne pourrez pas faire une demande nécessitant un contrôle en amont.
Il vous permettra de faire une simple demande, de ne pas voir la réponse et de ne pas remplir la Developer Console de messages d'erreur.
Comment le faire est expliqué par le message d'erreur Chrome donné lorsque vous faites une demande en utilisant fetch
et n'obtenez pas l'autorisation d'afficher la réponse avec CORS:
L'accès à la récupération à « https://example.com/
» de l'origine » https://example.net
a été bloqué par la politique CORS: aucun en Access-Control-Allow-Origin
-tête « »n'est présent sur la ressource demandée. Si une réponse opaque répond à vos besoins, définissez le mode de la requête sur «no-cors» pour récupérer la ressource avec CORS désactivé.
Donc:
fetch("http://example.com", { mode: "no-cors" });
Alternatives à CORS
JSONP
Bob pourrait également fournir les données en utilisant un hack comme JSONP, c'est ainsi que les gens ont créé Ajax d'origine croisée avant l'arrivée de CORS.
Il fonctionne en présentant les données sous la forme d'un programme JavaScript qui injecte les données dans la page de Mallory.
Cela exige que Mallory fasse confiance à Bob pour ne pas fournir de code malveillant.
Notez le thème commun: le site fournissant les données doit indiquer au navigateur qu'il est OK pour un site tiers d'accéder aux données qu'il envoie au navigateur.
Puisque JSONP fonctionne en ajoutant un <script>
élément pour charger les données sous la forme d'un programme JavaScript qui appelle une fonction déjà dans la page, essayer d'utiliser la technique JSONP sur une URL qui retourne JSON échouera - généralement avec une erreur CORB - car JSON n'est pas JavaScript.
Déplacer les deux ressources vers une seule origine
Si le document HTML dans lequel le JS s'exécute et que l'URL demandée est sur la même origine (partageant le même schéma, le même nom d'hôte et le même port), alors la même politique d'origine accorde l'autorisation par défaut. CORS n'est pas nécessaire.
Un proxy
Mallory pourrait utiliser du code côté serveur pour récupérer les données (qu'elle pourrait ensuite transmettre de son serveur au navigateur d'Alice via HTTP comme d'habitude).
Ce sera soit:
- ajouter des en-têtes CORS
- convertir la réponse en JSONP
- existent sur la même origine que le document HTML
Ce code côté serveur peut être écrit et hébergé par un tiers (tel que CORS Anywhere). Notez les implications de ceci en matière de confidentialité: le tiers peut surveiller qui proxie quoi sur ses serveurs.
Bob n'aurait pas besoin d'accorder d'autorisations pour que cela se produise.
Il n'y a pas d'implication de sécurité ici puisque c'est juste entre Mallory et Bob. Il n'y a aucun moyen pour Bob de penser que Mallory est Alice et de fournir à Mallory des données qui devraient rester confidentielles entre Alice et Bob.
Par conséquent, Mallory ne peut utiliser cette technique que pour lire des données publiques .
Notez cependant que prendre du contenu sur le site Web de quelqu'un d'autre et l'afficher vous-même peut constituer une violation du droit d' auteur et vous ouvrir à des poursuites judiciaires.
Écrire autre chose qu'une application Web
Comme indiqué dans la section «Pourquoi la politique de même origine ne s'applique qu'à JavaScript dans une page Web», vous pouvez éviter la SOP en n'écrivant pas de JavaScript dans une page Web.
Cela ne signifie pas que vous ne pouvez pas continuer à utiliser JavaScript et HTML, mais vous pouvez le distribuer en utilisant un autre mécanisme, tel que Node-WebKit ou PhoneGap.
Extensions de navigateur
Il est possible pour une extension de navigateur d'injecter les en-têtes CORS dans la réponse avant que la politique de même origine ne soit appliquée.
Celles-ci peuvent être utiles pour le développement, mais ne sont pas pratiques pour un site de production (demander à chaque utilisateur de votre site d'installer une extension de navigateur qui désactive une fonction de sécurité de son navigateur est déraisonnable).
Ils ont également tendance à ne fonctionner qu'avec des requêtes simples (échec lors du traitement des requêtes OPTIONS en amont).
Avoir un environnement de développement approprié avec un serveur de développement local
est généralement une meilleure approche.
Autres risques de sécurité
Notez que SOP / CORS n'atténue pas les attaques XSS , CSRF ou SQL Injection qui doivent être gérées indépendamment.
Résumé
- Il n'y a rien que vous puissiez faire dans votre code côté client qui permettra l'accès CORS au serveur de quelqu'un d' autre .
- Si vous contrôlez le serveur auquel la demande est adressée: Ajoutez-y des autorisations CORS.
- Si vous êtes ami avec la personne qui le contrôle: demandez-lui d'ajouter des autorisations CORS.
- S'il s'agit d'un service public:
- Lisez la documentation de leur API pour voir ce qu'ils disent sur l'accès avec JavaScript côté client:
- Ils pourraient vous dire d'utiliser des URL spécifiques
- Ils pourraient prendre en charge JSONP
- Ils peuvent ne pas du tout prendre en charge l'accès inter-origine à partir du code côté client (cela peut être une décision délibérée pour des raisons de sécurité, en particulier si vous devez passer une clé API personnalisée dans chaque demande).
- Assurez-vous de ne pas déclencher une demande de contrôle en amont dont vous n'avez pas besoin. L'API peut accorder une autorisation pour des demandes simples, mais pas des demandes de contrôle en amont.
- Si aucune des situations ci-dessus ne s'applique: demandez au navigateur de parler à votre serveur à la place, puis demandez à votre serveur de récupérer les données de l'autre serveur et de les transmettre. (Il existe également des services hébergés tiers qui attachent des en-têtes CORS à des ressources accessibles au public que vous pouvez utiliser).