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

111

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

J'ai un processus Grunt qui lance une instance de serveur express.js. Cela fonctionnait parfaitement jusqu'à maintenant, lorsqu'il a commencé à servir une page vierge avec les éléments suivants apparaissant dans le journal des erreurs de la console du développeur dans Chrome (dernière version):

XMLHttpRequest ne peut pas charger https://www.example.com/ Aucun en-tête 'Access-Control-Allow-Origin' n'est présent sur la ressource demandée. L' accès à l' origine ' http: // localhost: 4300 ' n'est donc pas autorisé.

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

Peter David Carter
la source
Je travaille sur le site Web et c'était bien il y a cinq minutes.
Peter David Carter
1
émet-il des en-têtes CORS? peut-être que si vous
partagiez du
Plausiblement. Quel département dois-je demander pour le savoir? Je fais juste les trucs de backbone.marionette principalement ...
Peter David Carter
Ouais. Je suppose que les organisations des départements ne sont pas toujours uniformes de toute façon, donc c'est peut-être une question nébuleuse, mais j'aimerais en savoir un peu plus sur le backend / routage / sys-admin de mon entreprise et cela m'a semblé être une bonne excuse pour me familiariser moi-même, donc s'il y a des problèmes à l'avenir, je peux aider.
Peter David Carter
Je demanderais à quelqu'un du côté serveur à l'intérieur de votre opération. Ils doivent l'avoir changé sur vous si vous avez pu y accéder auparavant.
Larry Lane

Réponses:

205

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:4300dans 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 XMLHttpRequestet 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-Originen- 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.

Modèle d'application des règles CORS

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-Originqu'à 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, POSTou ce que vous essayiez d'envoyer) et y répondre avec le droit Access-Control-Allow-Originheader mais aussi Access-Control-Allow-Methodset Access-Control-Allow-Headerspour 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-Originet 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/jsontê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-Typeet 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' fetchAPI (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 fetchet 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.neta é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).
Quentin
la source
Si j'exécute un réseau local sur un serveur Web et que j'essaie de charger ajax à partir de l'adresse IP / URL, cela fonctionnera-t-il? Je n'ai pas encore essayé cela. car mon serveur Web returing les données json serait un MCU
Ciasto piekarz
@Ciastopiekarz - Des règles normales de même origine / d'origine différente s'appliquent. Les règles de routage réseau normales s'appliquent.
Quentin
25
La réponse la plus complète que j'ai jamais lue, au lieu d'un simple lien sur les cors ..
pungggi
@Quentin - Wow! +1! Donc, ce que je dois comprendre, c'est que si Alice utilise l'extension CORS, le serveur pense que ses appels http ne proviennent pas de javascript mais d'une extension de navigateur et le traite comme une même requête d'origine normale?
snippetkid
@snippetkid - Non. Dans le cas habituel, le serveur enverra des en-têtes CORS dans chaque réponse sans se soucier de l'origine de la requête. Il est de la responsabilité du navigateur d'autoriser ou de refuser l'accès aux données du JS en fonction des en-têtes CORS de la réponse. (Les choses deviennent un / peu / plus complexes sur le serveur en ce qui concerne les demandes de contrôle en amont)
Quentin
3

Le serveur cible doit autoriser la demande d’origine croisée. Afin de l'autoriser via express, gérez simplement la demande d'options 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);
});
Daphoque
la source
3

Comme cela n'est pas mentionné dans la réponse acceptée.

  • Ce n'est pas le cas pour cette question exacte, mais cela pourrait aider d'autres personnes qui recherchent ce problème
  • C'est quelque chose que vous pouvez faire dans votre code client pour éviter les erreurs CORS dans certains cas .

Vous pouvez utiliser les requêtes simples .
Afin d'effectuer des «demandes simples», la demande doit remplir plusieurs conditions. Par exemple POST, autoriser uniquement , GETet HEADméthode, ainsi que n'autoriser que certains en-têtes donnés (vous pouvez trouver toutes les conditions ici ).

Si votre code client ne définit pas explicitement les en-têtes affectés (par exemple, "Accepter") avec une valeur de correction dans la demande, il se peut que certains clients définissent automatiquement ces en-têtes avec des valeurs "non standard", ce qui fait que le serveur ne les accepte pas comme Requête simple - qui vous donnera une erreur CORS.

zwif
la source
2

Cela se produit à cause de l'erreur CORS. CORS signifie Cross Origin Resource Sharing. En termes simples, cette erreur se produit lorsque nous essayons d'accéder à un domaine / une ressource à partir d'un autre domaine.

En savoir plus à ce sujet ici: Erreur CORS avec jquery

Pour résoudre ce problème, si vous avez accès à l'autre domaine, vous devrez autoriser Access-Control-Allow-Origin sur le serveur. Cela peut être ajouté dans les en-têtes. Vous pouvez l'activer pour toutes les demandes / domaines ou un domaine spécifique.

Comment faire fonctionner une demande de publication de partage de ressources croisées (CORS)

Ces liens peuvent aider

Vishnu
la source
0

Ce problème CORS n'a pas été approfondi (pour d'autres causes).

J'ai ce problème actuellement sous une raison différente. Mon frontal renvoie également une erreur d'en-tête `` Access-Control-Allow-Origin ''.

Juste que j'ai pointé la mauvaise URL afin que cet en-tête ne soit pas reflété correctement (dans lequel je présumais que c'était le cas). localhost (frontal) -> appel à http non sécurisé (supposé être https), assurez-vous que le point de terminaison de l'API du front-end pointe vers le bon protocole.

morph85
la source
0

J'ai eu la même erreur dans la console Chrome.

Mon problème était que j'essayais d'accéder au site en utilisant http://au lieu de https://. Il n'y avait donc rien à réparer, il fallait juste aller sur le même site en utilisant https.

Subhashi
la source
-1

La demande "Get" avec ajout d'en-têtes se transforme en demande "Options". Des problèmes de politique Cors surviennent donc. Vous devez implémenter la requête "Options" sur votre serveur.

kira
la source
-6

Vous devez activer CORS pour le faire fonctionner.

Perostek Balveda
la source