Maison  >  Questions et réponses  >  le corps du texte

XMLHttpRequest ne peut pas charger XXX, pas d'en-tête 'Access-Control-Allow-Origin'

tl;dr; À propos de la politique de même origine

J'ai un processus Grunt qui démarre une instance du serveur express.js. Tout cela fonctionnait parfaitement jusqu'à présent, mais maintenant, il commence à afficher une page blanche et affiche ce qui suit dans le journal des erreurs de la console développeur de Chrome (dernière version) :

XMLHttpRequest ne peut pas charger https://www.example.com/ Il n’y a pas d’en-tête « Access-Control-Allow-Origin » sur la ressource demandée. Par conséquent, l'accès depuis « http://localhost:4300 » n'est pas autorisé.

Qu'est-ce qui m'empêche d'accéder à cette page ?

P粉574695215P粉574695215416 Il y a quelques jours623

répondre à tous(2)je répondrai

  • P粉513316221

    P粉5133162212023-09-22 13:19:00

    Le serveur cible doit autoriser les requêtes inter-domaines. Afin de l'autoriser via express, il suffit de gérer la demande d'option http :

    app.options('/url...', function(req, res, next){
       res.header('Access-Control-Allow-Origin', "*");
       res.header('Access-Control-Allow-Methods', 'POST');
       res.header("Access-Control-Allow-Headers", "accept, content-type");
       res.header("Access-Control-Max-Age", "1728000");
       return res.sendStatus(200);
    });

    répondre
    0
  • P粉953231781

    P粉9532317812023-09-22 00:17:22

    tl;dr — Lorsque vous souhaitez lire des données, (principalement) à l'aide de JS côté client, à partir d'un autre serveur, vous avez besoin que le serveur contenant les données accorde une autorisation explicite au code qui souhaite les données.

    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 cela fournit des informations utiles pour comprendre le pourquoi, ce qui permet de voir plus facilement comment le comment s'applique dans différentes circonstances.

    À propos de la politique de même origine

    Il s'agit de la Politique de même origine. Il s'agit d'une fonctionnalité 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 il s'applique également à d'autres choses (comme les images chargées sur un <canvas> or documents loaded into an <iframe>), juste avec des implémentations légèrement différentes .

    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 possédant un navigateur Web
    • Bob gère un site Web (https://www.example.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 de l'intranet de l'entreprise (accessible uniquement aux navigateurs du réseau local) ou de sa banque en ligne (accessible uniquement avec un cookie que vous obtenez après avoir saisi un nom d'utilisateur et un mot de passe).

    Alice visite le site Web de Mallory qui contient du JavaScript qui amène le navigateur d'Alice à envoyer une requête HTTP au site Web de Bob (à partir de son adresse IP avec ses cookies, etc.). Cela pourrait être aussi simple que d'utiliser XMLHttpRequest and reading the 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 élément <img> à travers les origines car le contenu de l'image n'est pas exposé à JavaScript (ou Mallory)… à moins que vous ne jetiez un canevas dans le mélange, auquel cas vous générez un erreur de violation de même origine).


    Pourquoi la politique de même origine s'applique alors que vous pensez qu'elle ne devrait pas le faire

    Pour une URL donnée, il est possible que la SOP ne soit pas nécessaire. Voici quelques scénarios courants dans lesquels tel 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 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 transmette les données qu'il a reçues de Bob à un autre site Web.


    Pourquoi la politique de même origine s'applique au JavaScript dans une page Web mais rien d'autre

    En dehors de la page Web

    Les

    Extensions de navigateur*, l'onglet Réseau dans les outils de développement du navigateur et les applications comme Postman sont des logiciels installés. Ils ne transmettent pas de données d'un site Web au JavaScript appartenant à un autre site Web simplement parce que vous avez visité cet autre site Web. L'installation d'un logiciel nécessite 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. Voir la documentation Chrome par exemple.

    Dans la page Web

    La plupart du temps, il n'y a pas beaucoup de fuite d'informations lorsqu'il suffit d'afficher quelque chose sur une page Web.

    Si vous utilisez un attribut <img> element to load an image, then it gets shown on the page, but very little information is exposed to Mallory. JavaScript can't read the image (unless you use a crossOrigin pour activer explicitement l'autorisation de demande avec CORS), puis copiez-le sur son serveur.

    Cela dit, certaines informations fuient, pour citer Domenic Denicola (de Google) :

    C'est pourquoi vous avez besoin de l'autorisation CORS pour charger des polices sur plusieurs origines.


    Pourquoi pouvez-vous afficher des données sur la page sans les lire avec JS

    Il existe un certain nombre de circonstances dans lesquelles le site de Mallory peut amener un navigateur à récupérer des données auprès d'un tiers et à les afficher (par exemple en ajoutant un élément <img> pour afficher une image). Il n'est cependant 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, le système est donc toujours sécurisé.


    CORS

    L'en-tête Access-Control-Allow-Origin HTTP response 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 uniquement à un site spécifique d'y accéder, et Bob peut générer cela dynamiquement en fonction de l'en-tête Origin request 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. Les utilisateurs de Node.js/Express.js doivent utiliser le middleware CORS bien documenté. Les utilisateurs d'autres plates-formes devraient jeter un œil à cette collection de guides pour diverses configurations courantes qui pourraient aider.

    NB : Certaines requêtes sont complexes et envoient une requête preflight OPTIONS à laquelle le serveur devra répondre avant que le navigateur n'envoie la requête GET/POST/PUT/Whatever que le JS souhaite faire. Les implémentations de CORS qui ajoutent uniquement Access-Control-Allow-Origin à des URL spécifiques sont souvent perturbées par cela.


    Évidemment, accorder une autorisation via CORS est quelque chose que Bob ne ferait que si :

    • Les données n'étaient pas privées ou
    • Mallory avait confiance

    Comment ajouter ces en-têtes ?

    Cela dépend de votre environnement côté serveur.

    Si vous le pouvez, utilisez une bibliothèque conçue pour gérer CORS car elle vous présentera des options simples au lieu d'avoir à tout gérer manuellement.

    Enable-Cors.org propose une liste de documentation pour des plates-formes et des frameworks spécifiques qui pourraient vous être utiles.

    Mais je ne suis pas Bob !

    Il n'existe 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 requête d'une certaine manière, ou une option de configuration après s'être connecté à un site du 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 mentionnant "Réponse pour le contrôle en amont"

    Certaines demandes d'origine croisée font l'objet d'un contrôle en amont.

    Cela se produit lorsque (en gros) vous essayez de faire une demande d'origine croisée qui :

    • Comprend des informations d'identification telles que les cookies
    • Ne peut pas être généré avec un formulaire HTML standard (par exemple, définit un type de contenu que vous ne pouvez pas utiliser dans un formulaire enctype ou dans un ou plusieurs autres en-têtes de requête).

    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 (and not GET, POST, or whatever you were trying to send) and respond to it with the right Access-Control-Allow-Origin header but also Access-Control-Allow-Methods and 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 la nécessité 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 :

    • essaie de mettre Access-Control-Allow-Origin et d'autres en-têtes de réponse CORS sur la demande. Ceux-ci n'appartiennent pas à la demande, ne font rien d'utile (à quoi servirait un système d'autorisations où vous pourriez vous accorder la permission ?) et doivent apparaître uniquement sur la réponse.
    • j'essaie de mettre un Content-Type: application/json header on a GET request that has no request body the content of which to describe (typically when the author confuses Content-Type and Accept).

    Dans l'un ou l'autre de ces cas, la suppression de l'en-tête de requête 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 prenant en charge les requêtes simples mais pas les requêtes pré-volées).


    Réponses opaques (mode no-cors)

    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 le fetch API (rather than XMLHttpRequest), vous pouvez le configurer pour ne pas essayer d'utiliser CORS.

    Notez que cela ne vous permettra pas de faire tout ce que vous demandez à CORS de faire. Vous ne pourrez pas lire la réponse. Vous ne pourrez pas faire de demande nécessitant un contrôle en amont.

    Cela vous permettra de faire une simple demande, de ne pas voir la réponse et de ne pas remplir la console de développement de messages d'erreur.

    Comment procéder est expliqué par le message d'erreur Chrome donné lorsque vous faites une demande en utilisant fetch et que vous n'obtenez pas l'autorisation d'afficher la réponse avec CORS :

    Ainsi :

    fetch("http://example.com", { mode: "no-cors" });

    Alternatives au CORS

    JSONP

    Bob pourrait également fournir les données à l'aide d'un hack comme JSONP, c'est ainsi que les gens utilisaient Ajax d'origine croisée avant l'arrivée de CORS.

    Cela 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 nécessite 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 acceptable qu'un site tiers accède aux données qu'il envoie au navigateur.

    Étant donné que JSONP fonctionne en ajoutant un élément <script> pour charger les données sous la forme d'un programme JavaScript qui appelle une fonction déjà dans la page, tenter d'utiliser la technique JSONP sur une URL qui renvoie JSON échouera - généralement avec une erreur CORB - parce que JSON n'est pas JavaScript.

    Déplacez les deux ressources vers une seule Origine

    Si le document HTML dans lequel le JS s'exécute et l'URL demandée se trouvent sur la même origine (partageant le même schéma, le même nom d'hôte et le même port), la politique de même 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
    • existe 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 proxy quoi sur ses serveurs.

    Bob n'aurait pas besoin d'accorder d'autorisations pour que cela se produise.

    Il n'y a aucune implication en matière de sécurité ici puisque cela ne concerne que 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 par vous-même peut constituer une violation du droit d'auteur et vous exposer à des poursuites judiciaires.

    Écrire autre chose qu'une application web

    Comme indiqué dans la section « Pourquoi la politique de même origine s'applique uniquement au JavaScript dans une page Web », vous pouvez éviter le 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 les distribuer en utilisant un autre mécanisme, tel que Node-WebKit ou PhoneGap.

    Extensions de navigateur

    Il est possible qu'une extension de navigateur injecte les en-têtes CORS dans la réponse avant que la politique de même origine ne soit appliquée.

    Ceux-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 fonctionnalité de sécurité de son navigateur est déraisonnable).

    Ils ont également tendance à fonctionner uniquement avec des requêtes simples (échouant 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énuent pas les attaques XSS, CSRF ou SQL Injection qui doivent être gérées indépendamment.


    Résumé

    • Vous ne pouvez rien faire dans votre code côté client qui permettra à CORS d'accéder au serveur d'autre de quelqu'un d'autre.
    • Si vous contrôlez le serveur, la demande est faite pour : Ajoutez-y des autorisations CORS.
    • Si vous êtes ami avec la personne qui le contrôle : demandez-lui d'y ajouter des autorisations CORS.
    • S'il s'agit d'un service public, alors (en gardant à l'esprit que la plupart des API tierces sont conçues pour interagir uniquement avec votre code côté serveur et ne prennent pas en charge CORS mais pour celles qui le sont) :
      • Lisez la documentation de leur API pour voir ce qu'ils disent sur l'accès avec JavaScript côté client :
        • Ils pourraient vous demander d'utiliser des URL spécifiques
        • Ils pourraient prendre en charge JSONP au lieu de CORS
        • Ils peuvent ne pas prendre en charge l'accès multi-origine à partir du code côté client (cela peut être une décision délibérée pour des raisons de sécurité, surtout si vous devez transmettre une clé API personnalisée dans chaque requête).
      • Assurez-vous de ne pas déclencher une demande de contrôle en amont dont vous n'avez pas besoin. L'API peut accorder l'autorisation pour des requêtes simples, mais pas pour des requêtes préliminaires.
    • 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 publiquement que vous pouvez utiliser).

    répondre
    0
  • Annulerrépondre