web-dev-qa-db-fra.com

Comment fonctionne l'en-tête Access-Control-Allow-Origin?

Apparemment, j'ai complètement mal compris sa sémantique. J'ai pensé à quelque chose comme ça:

  1. Un client télécharge le code javascript MyCode.js à partir de http: // siteA - the Origin.
  2. L'en-tête de réponse de MyCode.js contient Access-Control-Allow-Origin: http: // siteB, ce qui, je le pensais, signifiait que MyCode.js était autorisé à faire des références croisées au site B.
  3. Le client déclenche certaines fonctionnalités de MyCode.js, qui à leur tour adressent des requêtes à http: // siteB, ce qui devrait bien se passer, même s'il s'agit de requêtes croisées.

Eh bien, je me trompe. Cela ne marche pas du tout comme ça. Donc, j'ai lu Partage de ressources d'origine croisée et j'ai essayé de lire Partage de ressources d'origine croisée dans la recommandation w3c

Une chose est sûre: je ne comprends toujours pas comment je suis censé utiliser cet en-tête. 

J'ai le contrôle total du site A et du site B. Comment puis-je activer le code javascript téléchargé à partir du site A pour accéder aux ressources du site B à l'aide de cet en-tête?

P.S.

Je ne veux pas utiliser JSONP.

891
mark

Access-Control-Allow-Origin est un en-tête CORS (Cross-Origin Resource Sharing) .

Lorsque le site A tente d'extraire du contenu du site B, le site B peut envoyer un en-tête de réponse Access-Control-Allow-Origin pour indiquer au navigateur que le contenu de cette page est accessible à certaines origines. (Un Origine est un domaine , ainsi qu'un schéma et un numéro de port .) Par défaut, les pages du site B sont inaccessibles à toute autre origine ; L'utilisation de l'en-tête Access-Control-Allow-Origin ouvre une porte d'accès croisé entre origines requérantes spécifiques.

Pour chaque ressource/page que le site B souhaite rendre accessible au site A, le site B doit afficher ses pages avec l'en-tête de réponse:

Access-Control-Allow-Origin: http://siteA.com

Les navigateurs modernes ne bloqueront pas les demandes interdomaines. Si le site A demande une page au site B, le navigateur récupérera la page demandée au niveau du réseau} _ et vérifiera si les en-têtes de réponse répertorient le site A en tant que domaine demandeur autorisé. Si le site B n'a pas indiqué que le site A est autorisé à accéder à cette page, le navigateur déclenche l'événement XMLHttpRequest 's error et refuse les données de réponse au code JavaScript demandeur.

Requêtes non simples

Ce qui se passe au niveau du réseau peut être légèrement plus complexe que celui expliqué ci-dessus. Si la demande est une demande "non simple" , le navigateur envoie d'abord une demande OPTIONS sans contrôle de données, afin de vérifier que le serveur accepte la demande. Une demande n'est pas simple lorsque l'une ou l'autre (ou les deux):

  • utilisant un verbe HTTP autre que GET ou POST (par exemple, PUT, DELETE)
  • utiliser des en-têtes de requête non simples; les seuls en-têtes de demandes simples sont:
    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type (ceci n'est simple que lorsque sa valeur est application/x-www-form-urlencoded, multipart/form-data ou text/plain)

Si le serveur répond au contrôle en amont des options avec les en-têtes de réponse appropriés (Access-Control-Allow-Headers pour les en-têtes non simples, Access-Control-Allow-Methods pour les verbes non simples) correspondant aux en-têtes non simples et/ou non simples, le navigateur envoie la demande réelle.

En supposant que le site A souhaite envoyer une demande PUT pour /somePage, avec une valeur non-simple Content-Type de application/json, le navigateur enverra d'abord une demande de contrôle en amont:

OPTIONS /somePage HTTP/1.1
Origin: http://siteA.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type

Notez que Access-Control-Request-Method et Access-Control-Request-Headers sont ajoutés automatiquement par le navigateur. vous n'avez pas besoin de les ajouter. Ce contrôle en amont des options obtient les en-têtes de réponse réussie:

Access-Control-Allow-Origin: http://siteA.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Content-Type

Lors de l'envoi de la demande réelle (après le contrôle en amont), le comportement est identique à la manière dont une demande simple est traitée. En d’autres termes, une requête non simple dont le contrôle en amont a réussi est traitée de la même manière qu’une requête simple (c’est-à-dire que le serveur doit toujours envoyer à nouveau Access-Control-Allow-Origin pour la réponse réelle).

Les navigateurs envoient la demande réelle:

PUT /somePage HTTP/1.1
Origin: http://siteA.com
Content-Type: application/json

{ "myRequestContent": "JSON is so great" }

Et le serveur renvoie un Access-Control-Allow-Origin, comme pour une simple requête:

Access-Control-Allow-Origin: http://siteA.com

Voir Comprendre XMLHttpRequest sur CORS pour un peu plus d'informations sur les requêtes non simples.

1150
apsillers

Le partage de requêtes entre plusieurs origines - CORS (demande AKA entre plusieurs domaines AJAX) est un problème que la plupart des développeurs Web pourraient rencontrer. Selon Same-Origin-Policy, les navigateurs restreignent le code JavaScript du client dans un sandbox de sécurité. En général, JS ne peut pas le faire directement. communiquer avec un serveur distant d'un autre domaine. Auparavant, les développeurs créaient de nombreuses méthodes délicates pour répondre aux demandes de ressources inter-domaines, notamment:

  1. Utilisez Flash/Silverlight ou le côté serveur en tant que "proxy" pour communiquer Avec distant. 
  2. JSON avec rembourrage ( JSONP ). 
  3. Intègre un serveur distant dans une iframe et communique via fragment ou window.name, reportez-vous à ici .

Ces solutions compliquées présentent plus ou moins quelques problèmes. Par exemple, JSONP risque de créer une faille de sécurité si les développeurs la "valident" simplement et n ° 3 ci-dessus. Bien que cela fonctionne, les deux domaines doivent établir un contrat strict entre eux, sans souplesse ni élégance. A MON HUMBLE AVIS:)

Le W3C a introduit le partage de ressources d'origine croisée (CORS) en tant que solution standard pour fournir un moyen standard sûr et flexible et recommandé de résoudre ce problème. 

Le mécanisme

A un niveau élevé, nous pouvons simplement considérer que CORS est un contrat entre un appel client AJAX du domaine A et une page hébergée sur le domaine B, une demande/réponse typique de Cross-Origin serait:

DomainA AJAX en-têtes de demande

Host DomainB.com
User-Agent Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0) Gecko/20100101 Firefox/4.0
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8,application/json
Accept-Language en-us;
Accept-Encoding gzip, deflate
Keep-Alive 115
Origin http://DomainA.com 

En-têtes de réponse DomainB

Cache-Control private
Content-Type application/json; charset=utf-8
Access-Control-Allow-Origin DomainA.com
Content-Length 87
Proxy-Connection Keep-Alive
Connection Keep-Alive

Les parties bleues que j’ai marquées ci-dessus étaient des faits essentiels, l’en-tête de requête "Origine" indique l’origine de la demande de contrôle de contrôle ou de contrôle en provenance de l'origine ", l'en-tête de réponse" Contrôle d'accès-autorisation-d'origine "indique que cette page autorise la demande à distance DomainA (si la valeur est *, indiquez si vous autorisez les requêtes distantes depuis n'importe quel domaine).

Comme je l'ai mentionné plus haut, W3 a recommandé au navigateur d'implémenter une "requête preflight" avant de soumettre la requête HTTP véritablement d'origine croisée. En bref, il s'agit d'une requête HTTP OPTIONS:

OPTIONS DomainB.com/foo.aspx HTTP/1.1

Si foo.aspx prend en charge le verbe OPTIONS HTTP, il peut renvoyer une réponse comme ci-dessous:

HTTP/1.1 200 OK
Date: Wed, 01 Mar 2011 15:38:19 GMT
Access-Control-Allow-Origin: http://DomainA.com
Access-Control-Allow-Methods: POST, GET, OPTIONS, HEAD
Access-Control-Allow-Headers: X-Requested-With
Access-Control-Max-Age: 1728000
Connection: Keep-Alive
Content-Type: application/json

Seulement si la réponse contient "Access-Control-Allow-Origin" ET si sa valeur est "*" ou contient le domaine qui a soumis la demande CORS, en satisfaisant cette condition obligatoire, le navigateur soumettra la demande réelle à plusieurs domaines et mettra en cache le résultat. dans "Preflight-Result-Cache".

J'ai blogué à propos de CORS il y a trois ans: AJAX Requête HTTP Cross-Origin

107
Wayne Ye

La question est un peu trop ancienne pour y répondre, mais je la poste pour toute référence future à cette question.

Selon this article de Mozilla Developer Network,

Une ressource crée une requête HTTP multi-origine lorsqu'elle demande une ressource à un domaine ou à un port différent de celui que la première ressource sert elle-même.

 enter image description here

Un page HTML servi depuis http://domain-a.com fait une demande src <img> pour http://domain-b.com/image.jpg.
Aujourd'hui, de nombreuses pages Web chargent des ressources telles que feuilles de style CSS, images et scripts à partir de domaines distincts (cela devrait donc être cool).

Politique de même origine

Pour des raisons de sécurité, les navigateurs limitent les HTTP d'origine croisée _ requêtes initiées à partir de scripts.
Par exemple, XMLHttpRequest et Fetch suivent la règle de même origine.
Ainsi, une application Web utilisant XMLHttpRequest ou Fetch ne peut que rendre requêtes HTTP à son propre domaine.

Partage de ressources d'origine croisée (CORS)

Pour améliorer les applications Web, les développeurs ont demandé aux fournisseurs de navigateurs d'autoriser les requêtes interdomaines.

Le mécanisme CORS) donne aux serveurs Web contrôles d'accès entre domaines, qui permettent des transferts de données entre domaines sécurisés.
Les navigateurs modernes utilisent CORS dans un conteneur d'API - tel que XMLHttpRequest ou Fetch - pour atténuer les risques liés aux requêtes HTTP d'origine croisée.

Comment fonctionne CORS (en-tête Access-Control-Allow-Origin)

Wikipédia :

La norme CORS décrit les nouveaux en-têtes HTTP qui fournissent aux navigateurs et aux serveurs un moyen de demander des URL distantes uniquement lorsqu'ils disposent de l'autorisation.

Bien que certaines validations et autorisations puissent être effectuées par le serveur, c'est généralement la responsabilité du navigateur de prendre en charge ces en-têtes et de respecter les restrictions qu'ils imposent.

Exemple

  1. Le navigateur envoie la demande OPTIONS avec un en-tête Origin HTTP

    La valeur de cet en-tête est le domaine qui a servi la page parent. Lorsqu'une page de http://www.example.com tente d'accéder aux données d'un utilisateur dans service.example.com, l'en-tête de requête suivant est envoyé à service.example.com:

    Origine: http://www.example.com

  2. Le serveur à service.example.com peut répondre avec:

    • Un en-tête Access-Control-Allow-Origin (ACAO) dans sa réponse indiquant les sites d'origine autorisés.
      Par exemple: 

      Access-Control-Allow-Origin: http://www.example.com

    • Une page d'erreur si le serveur n'autorise pas la demande d'origine croisée

    • Un en-tête Access-Control-Allow-Origin (ACAO) avec un caractère générique qui autorise tous les domaines:

      Access-Control-Allow-Origin: *

42
Trix

En utilisant React et Axios , joignez un lien proxy à l’URL et ajoutez un en-tête comme indiqué ci-dessous

https://cors-anywhere.herokuapp.com/ + Your API URL

Simplement en ajoutant le lien Proxy fonctionnera, mais il peut également renvoyer une erreur pour No Access à nouveau. Il est donc préférable d’ajouter un en-tête comme indiqué ci-dessous.

axios.get(`https://cors-anywhere.herokuapp.com/[YOUR_API_URL]`,{headers: {'Access-Control-Allow-Origin': '*'}})
      .then(response => console.log(response:data);
  }
8
Dhaval Jardosh

Si vous souhaitez simplement tester une application inter-domaines dans laquelle le navigateur bloque votre demande, vous pouvez simplement ouvrir votre navigateur en mode non sécurisé et tester votre application sans modifier votre code ni rendre votre code non sécurisé. peut le faire depuis la ligne de terminal:

open -a Google\ Chrome --args --disable-web-security --user-data-dir
8
Maurizio Brioschi

Chaque fois que je commence à penser à CORS, mon intuition quant au site qui héberge les en-têtes est incorrecte, tout comme vous l'avez décrit dans votre question. Pour moi, il est utile de réfléchir à l'objectif de la même politique d'origine.

L'objectif de la même stratégie Origin est de vous protéger contre le JavaScript malveillant sur siteA.com qui accède aux informations privées que vous avez choisi de partager uniquement avec siteB.com. Sans la même politique d'origine, les auteurs JavaScript de JavaScript rédigés par les auteurs de siteA.com pourraient demander à votre navigateur de demander à siteB.com, à l'aide de vos cookies d'authentification pour siteB.com. De cette manière, siteA.com pourrait voler les informations secrètes que vous partagez avec siteB.com.

Parfois, vous devez travailler sur plusieurs domaines, c'est là que CORS entre en jeu. CORS assouplit la même stratégie d'origine pour domainA.com, en utilisant l'en-tête Access-Control-Allow-Origin pour répertorier les autres domaines (domainB.com) autorisés à exécuter JavaScript et pouvant interagir avec domainA .com.

Pour comprendre quel domaine doit servir les en-têtes CORS, considérez ceci. Vous visitez le site malveillant.com, qui contient du code JavaScript qui tente d'envoyer une requête interdomaine à mybank.com. Il appartient à mybank.com, et non à malware.com, de décider s’il définit ou non les en-têtes CORS qui assouplissent la même stratégie Origin permettant au JavaScript de malveillant.com d’interagir avec lui. Si malicous.com pouvait définir ses propres en-têtes CORS autorisant son propre accès JavaScript à mybank.com, cela annulerait complètement la même politique d'origine. 

Je pense que la raison de ma mauvaise intuition est le point de vue que j'ai lors du développement d'un site. C'est mon site, avec tout mon JavaScript, donc il ne fait rien de malveillant et il devrait incomber à moi de spécifier avec quels autres sites mon JavaScript peut interagir avec . Quand, en fait, je devrais penser quels autres sites JavaScript essaient d'interagir avec mon site et devrais-je utiliser CORS pour les autoriser? 

7
Dom

1. Un client télécharge le code javascript MyCode.js depuis http: // siteA - the Origin.

Le code qui effectue le téléchargement - votre balise de script html ou xhr à partir de javascript ou autre - provient de, disons, http: // siteZ . Et, lorsque le navigateur demande MyCode.js, il envoie un en-tête Origin: "Origin: http: // siteZ ", car il peut voir que vous demandez à siteA et siteZ! = SiteA. (Vous ne pouvez pas arrêter ou interférer avec cela.)

2. L'en-tête de réponse de MyCode.js contient Access-Control-Allow-Origin: http: // siteB , ce qui, à mon avis, signifiait que MyCode.js était autorisé à faire des références croisées au site B .

non. Cela signifie que seul le site B est autorisé à effectuer cette demande. Donc, votre demande de MyCode.js auprès de siteZ obtient une erreur et le navigateur ne vous donne généralement rien. Mais si vous faites que votre serveur retourne A-C-A-O: siteZ à la place, vous obtiendrez MyCode.js. Ou si elle envoie '*', cela fonctionnera, cela laissera tout le monde entrer. Ou si le serveur envoie toujours la chaîne depuis l'en-tête Origin: ... mais ... pour la sécurité, si vous craignez les pirates , votre serveur ne doit autoriser que les origines de la liste restreinte, qui sont autorisées à effectuer ces demandes.

Ensuite, MyCode.js provient du siteA. Lorsqu'ils adressent des demandes à siteB, ils sont tous inter-origines, le navigateur envoie Origin: siteA et siteB doit prendre le siteA, le reconnaître sur la liste des demandeurs autorisés et renvoyer A-C-A-O: siteA. Ce n’est qu’alors que le navigateur laissera à votre script le résultat de ces requêtes.

6
OsamaBinLogin

je travaille avec express 4 et noeud 7.4 et angulaire, j'ai eu le même problème moi aider ceci:
a) côté serveur: dans le fichier app.js, je donne des en-têtes à toutes les réponses telles que:

app.use(function(req, res, next) {  
      res.header('Access-Control-Allow-Origin', req.headers.Origin);
      res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
      next();
 });  

cela doit avoir avant tout routeur .
J'ai vu beaucoup d'en-têtes ajoutés:

res.header("Access-Control-Allow-Headers","*");
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');

mais je n'ai pas besoin de ça,
b) côté client: dans send ajax, vous devez ajouter: "withCredentials: true," comme:

$http({
     method: 'POST',
     url: 'url, 
     withCredentials: true,
     data : {}
   }).then(function(response){
        // code  
   }, function (response) {
         // code 
   });

bonne chance.

6
izik f

Si vous utilisez PHP, essayez d'ajouter le code suivant à la fin du fichier php:

si vous utilisez localhost, essayez ceci:

header("Access-Control-Allow-Origin: *");

si vous utilisez des domaines externes tels que serveur, essayez ceci:

header("Access-Control-Allow-Origin: http://www.website.com");
3
Melvin Guerrero

Pour le partage d'origine croisée, définissez l'en-tête: 'Access-Control-Allow-Origin':'*';

Php: header('Access-Control-Allow-Origin':'*');

Node: app.use('Access-Control-Allow-Origin':'*');

Cela permettra de partager du contenu pour différents domaines.

2
suryadev

En Python, j'utilise la bibliothèque Flask-CORS avec beaucoup de succès. Cela rend la négociation avec CORS super facile et sans douleur. J'ai ajouté du code provenant de la documentation de la bibliothèque ci-dessous. 

Installation:

$ pip install -U flask-cors

Exemple simple permettant à CORS de gérer tous les domaines et toutes les routes:

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

@app.route("/")
def helloWorld():
  return "Hello, cross-Origin-world!"

Pour des exemples plus spécifiques, voir la documentation. J'ai utilisé l'exemple simple ci-dessus pour résoudre le problème de la CORS dans une application ionique que je construis et qui doit accéder à un serveur de flacon séparé.

2
agaidis

L'en-tête de réponse Access-Control-Allow-Origin indique si le la réponse peut être partagée avec le code demandeur provenant de l'origine donnée.

Header type Response       header
Forbidden header name      no

Une réponse qui indique au navigateur d'autoriser le code provenant de n'importe quelle origine à accéder à une ressource comprendra les éléments suivants:

Access-Control-Allow-Origin: *

Pour plus d'informations, visitez ici ....

0
Alireza

Collez simplement le code suivant dans votre fichier web.config.

Notez que vous devez coller le code suivant sous la balise <system.webServer>

    <httpProtocol>  
    <customHeaders>  
     <add name="Access-Control-Allow-Origin" value="*" />  
     <add name="Access-Control-Allow-Headers" value="Content-Type" />  
     <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />  
    </customHeaders>  
  </httpProtocol>  
0
Juboraj Sarker