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 ceci:
- un client télécharge le code javascript MyCode.js de http://siteA - "151940920 de" l'origine .
- l'en-tête de réponse de MyCode.js contient Access-Control-Allow-Origin: http://siteB , ce qui veut dire MyCode.js a été autorisée à faire des références croisées au site B.
- le client déclenche certaines fonctionnalités de MyCode.js, qui à son tour font des demandes à http://siteB, ce qui devrait être bien, bien qu'il s'agisse de demandes d'origine croisée.
Eh bien, je me trompe. Il ne fonctionne pas comme ça à tout. Ainsi, j'ai lu "Cross-origin resource sharing et tenté de lire "Cross-Origin Resource Sharing" dans la recommandation du w3c
"une chose est sûre - je le fais toujours Je ne comprends 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 en utilisant cet en-tête?
P. S.
Je ne veux pas utiliser JSONP.
11 réponses
Access-Control-Allow-Origin
est un en-tête CORS (Cross-Origin Resource Sharing) .
lorsque le Site a tente de récupérer 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, en plus d'un régime et le numéro de port .) Par défaut, les pages du Site B sont inaccessible à tout autre origine ; l'utilisation de l'en-tête Access-Control-Allow-Origin
ouvre une porte pour l'accès d'origine croisée par Origine spécifique demandant.
pour chaque ressource/page que le Site B veut rendre accessible au Site A, le Site B doit servir ses pages avec l'en-tête de réponse:
Access-Control-Allow-Origin: http://siteA.com
les navigateurs modernes ne bloqueront pas complètement les requêtes trans-domaine. Si le Site a demande une page du Site B, le navigateur récupérera la page demandée sur le niveau de réseau et vérifier si les en-têtes de réponse liste le Site A comme un domaine de demandeur autorisé. Si le Site B n'a pas indiqué que le Site A est autorisé à accéder à cette page, le navigateur déclenchera l'événement XMLHttpRequest
's error
et refusera les données de réponse au code JavaScript demandé.
Non de simples demandes
ce qui se passe au niveau du réseau peut être légèrement plus complexe que expliqué surtout. Si la requête est une "requête non simple , le navigateur envoie d'abord une requête D'OPTIONS" preflight "sans données, pour vérifier que le serveur acceptera la requête. Une requête n'est pas simple lorsque soit (soit les deux):
- utilisant un verbe HTTP autre que GET ou POST (p.ex. PUT, DELETE)
- utilisant des en-têtes de requêtes non simples; les seuls en-têtes de requêtes simples sont:
-
Accept
-
Accept-Language
-
Content-Language
-
Content-Type
(c'est seulement simple quand sa valeur estapplication/x-www-form-urlencoded
,multipart/form-data
, outext/plain
)
-
si le serveur répond aux OPTIONS pré-Light 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) qui correspondent au verbe non simple et / ou non simple les en-têtes, puis le navigateur envoie la demande réelle.
en supposant que le Site a veut envoyer une demande PUT pour /somePage
, avec une valeur non-simple Content-Type
de application/json
, le navigateur enverrait d'abord une demande preflight:
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. Cette option preflight obtient les en-têtes de réponse réussis:
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 requête réelle (après que le pré-vol est fait), le comportement est identique à la façon dont une requête simple est traitée. En d'autres termes, une requête non simple dont le pré-lancement est réussi est traitée de la même manière qu'une requête simple (c'est-à-dire que le serveur doit encore envoyer Access-Control-Allow-Origin
pour la réponse réelle).
les navigateurs envoient la requête 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
, juste comme pour une simple requête:
Access-Control-Allow-Origin: http://siteA.com
Voir Compréhension XMLHttpRequest au cours de la SCRO pour un peu plus d'informations à propos de la non-simple demande.
Cross-Origin Request Sharing - CORS
(A. K. A. Cross-Domain AJAX request) est un problème que la plupart des développeurs web peuvent rencontrer, selon Same-Origin-Policy, les navigateurs restreindre JavaScript client dans un bac à sable de sécurité, généralement JS ne peut pas communiquer directement avec un serveur distant à partir d'un domaine différent. Dans le passé, les développeurs ont créé de nombreuses façons délicates de réaliser des requêtes de ressources inter-domaines, le plus souvent en utilisant des moyens sont:
- utiliser Flash/Silverlight ou côté serveur comme un "proxy" pour communiquer avec la télécommande.
- JSON With Padding ( JSONP ).
- intègre un serveur distant dans une iframe et communique par fragment ou fenêtre.nom, se référer ici .
ces façons délicates ont plus ou moins certains problèmes, par exemple JSONP pourrait entraîner un trou de sécurité si les développeurs simplement "eval" it, et #3 ci-dessus, bien que cela fonctionne, les deux domaines devraient construire contrat strict entre eux, il ni souple ni élégant IMHO:)
le W3C avait introduit le partage des ressources Multi-origines (CORS) comme solution standard pour fournir une façon sûre, flexible et standard recommandée de résoudre ce problème.
Le Mécanisme
D'un haut niveau, nous pouvons simplement considérer que CORS est un contrat entre client AJAX appel du domaine A et une page hébergée sur le domaine B, une requête/réponse Type À origine croisée serait:
DomainA AJAX en-têtes de requête
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
DomainB en-têtes de réponse
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 marquées I ci-dessus étaient les faits principaux," L'en-tête de la demande "Origine" indique l'origine de la demande d'origine croisée ou de la demande avant le vol", "le contrôle D'accès-Autoriser-origine"." l'en-tête de réponse indique que cette page permet la requête à distance à partir de DomainA (si la valeur est * indiquer permet les requêtes à distance à partir de n'importe quel domaine).
comme je l'ai mentionné ci-dessus, W3 a recommandé le navigateur pour mettre en œuvre une" "demande pré-vol "avant de soumettre la demande HTTP réellement Cross-Origin, en un mot il s'agit D'une demande HTTP OPTIONS
:
OPTIONS DomainB.com/foo.aspx HTTP/1.1
Si foo.aspx supporte les OPTIONS HTTP verb, il peut renvoyer la 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 sa valeur est" * " ou contient le domaine qui a soumis la demande CORS, en satisfaisant à cette condition de mandtory le navigateur soumettra la demande transversale réelle de domaine, et cache le résultat dans " Preflight-Result-Cache ".
j'ai blogué sur CORS il y a trois ans: AJAX Cross-Origin HTTP request
Question est un peu trop vieux pour répondre, mais je poste ceci pour toute référence future à cette question.
selon ce article de Mozilla Developer Network,
une ressource fait une requête HTTP d'origine croisée lorsqu'elle demande une ressource à partir d'un domaine ou d'un port différent de celui que la première ressource elle-même sert.
Un page HTML servi de http://domain-a.com
prend un <img>
src demande de http://domain-b.com/image.jpg
.
De nombreuses pages sur le web aujourd'hui chargent des ressources comme CSS stylesheets , images et scripts de domaines séparés (donc il devrait être cool).
Politique De La Même Origine
pour des raisons de sécurité, les navigateurs restreignent origine croisée HTTP requests initiated from within scripts .
Par exemple, XMLHttpRequest
et Fetch
suivent la Politique de même origine .
Ainsi, une application web utilisant XMLHttpRequest
ou Fetch
ne pouvait faire que requêtes HTTP à son propre domaine .
Cross-Origin Resource Sharing (CORS)
pour améliorer les applications web, les développeurs ont demandé aux fournisseurs de navigateur pour autoriser les requêtes de domaine.
Le Cross-Origin Resource sharing (SCRO) mécanisme donne des serveurs web cross-domaine des contrôles d'accès , qui permet de sécuriser la croix-domaine des transferts de données.
Les navigateurs modernes utilisez CORS dans un conteneur API - tels que XMLHttpRequest
ou Fetch
- pour atténuer les risques de demandes HTTP d'origine croisée.
Comment la SCRO œuvres ( Access-Control-Allow-Origin
en-tête)
la norme CORS décrit les nouveaux en-têtes HTTP qui fournissent aux navigateurs et aux serveurs une façon de demander des URL distantes uniquement lorsqu'ils en ont la permission.
bien qu'une validation et une autorisation puissent être effectuées par le serveur, il est généralement de la responsabilité du navigateur de soutenir ces en-têtes et d'honorer les restrictions qu'ils imposent.
exemple
-
le navigateur envoie la demande
OPTIONS
avec un en-têteOrigin HTTP
.la valeur de cet en-tête est domaine qui a servi à la page mère. Lorsqu'une page de
http://www.example.com
tente d'accéder aux données d'un utilisateur dansservice.example.com
, l'en-tête de requête suivant serait envoyé àservice.example.com
:origine: http://www.example.com
-
le serveur à
service.example.com
peut répondre par:-
an
Access-Control-Allow-Origin
(ACAO) en-tête dans sa réponse indiquant sites d'origine sont autorisées.
Par exemple:Access-Control-Allow-Origin: http://www.example.com
-
une page d'erreur si le serveur ne permet pas la requête d'origine croisée
-
Un
Access-Control-Allow-Origin
(ACAO) de la tête avec un joker qui permet à tous les domaines:Access-Control-Allow-Origin: *
-
si vous voulez juste tester une application de domaine croisé dans laquelle le navigateur bloque votre demande, alors vous pouvez juste ouvrir votre navigateur en mode non sécuritaire et tester votre application sans changer votre code et sans rendre votre code dangereux. De MAC OS vous pouvez le faire à partir de la ligne de terminal:
open -a Google\ Chrome --args --disable-web-security --user-data-dir
utilisant React et Axios , joindre le lien proxy à L'URL et ajouter l'en-tête comme montré ci-dessous
https://cors-anywhere.herokuapp.com/
+ Your API URL
simplement en ajoutant le lien Proxy fonctionnera, mais il peut aussi lancer une erreur pour aucun accès à nouveau. Il est donc préférable d'ajouter l'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);
}
1. Un client télécharge le code javascript MyCode.js de http://siteA - l'origine.
le code qui fait le téléchargement-votre étiquette de script html ou xhr à partir de javascript ou autre - vient de, disons, http://siteZ . Et, quand le navigateur demande MyCode.js, il envoie une origine: en-tête disant "origine: http://siteZ ", parce qu'il peut voir que vous demandez à siteA et à siteZ != siteA. (Vous ne pouvez pas arrêter ou interférer avec ce.)
2. L'en-tête de réponse de MyCode.js contains Access-Control-Allow-Origin: http://siteB , ce qui veut dire MyCode.js a été autorisée à faire des références croisées au site B.
pas de. Cela signifie que seul siteB est autorisé à faire cette demande. Donc votre demande pour MyCode.js de siteZ obtient une erreur à la place, et le navigateur généralement vous donne rien. Mais si vous faites revenir votre serveur A-C-A-O: siteZ à la place, vous obtiendrez MyCode.js . Ou si ça envoie"*", ça marchera, ça 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 avez peur des hackers, votre serveur ne devrait autoriser que les origines sur une liste restreinte, qui sont autorisées à faire ces requêtes.
Alors, MyCode.js vient de siteA. Quand il fait des demandes à siteB, ils sont tout d'origine croisée, le navigateur envoie Origin: siteA, et siteB doit prendre le siteA, reconnaître qu'il est sur la courte liste des demandeurs autorisés, et renvoyer A-C-A-O: siteA. Alors seulement, le navigateur laissez votre script obtenez le résultat de ces demandes.
je travaille avec express 4 et node 7.4 et angular, j'ai eu le même problème que me aider à ceci:
a) côté serveur:dans l'application file.js-je donner des en-têtes à toutes les réponse du genre:
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 de ajouter ces en-têtes:
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 que,
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.
chaque fois que je commence à penser à CORS, mon intuition sur le site qui héberge les en-têtes est incorrecte, tout comme vous l'avez décrit dans votre question. Pour moi, cela aide de penser au but de la même politique d'origine.
le but de la même politique d'origine est de vous protéger contre le JavaScript malveillant sur siteA.com accès à des renseignements personnels que vous avez choisi de partager seulement avec siteB.com. Sans la même politique d'origine, JavaScript écrit par les auteurs de siteA.com pourrait faire votre navigateur faire des demandes à siteB.com, en utilisant vos cookies d'authentification pour siteB.com. De cette façon, siteA.com pourrait voler les informations secrètes que vous partagez avec siteA.com.
il faut parfois travailler le cross domain, c'est là que CORS intervient. CORS assouplit la même politique d'origine pour domainA.com, en utilisant l'en-tête Access-Control-Allow-Origin
pour lister d'autres domaines (domainB.com) qui sont fiables pour exécuter JavaScript qui peut interagir avec domainA.com.
pour comprendre quel domaine devrait servir les en-têtes CORS, considérez ceci. Vous visitez malicious.com, qui contient du JavaScript qui essaie de faire une requête de domaine croisée mybank.com. Il devrait être jusqu'à mybank.com, pas malicious.com, pour décider si oui ou non il fixe des en-têtes CORS qui assouplissent la même politique d'origine permettant le JavaScript de malicious.com pour interagir avec elle. Si c'était possible pour malicous.com pour configurer ses propres en-têtes CORS permettant 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. Son mon site, avec tous mon JavaScript, donc il ne fait rien de malveillant et il devrait être jusqu'à me pour préciser quels autres sites mon JavaScript peut interagir avec. Alors qu'en fait je devrais être pensez-vous que autres sites JavaScript tentent d'interagir avec mon site et devrais-je utiliser CORS pour leur permettre?
si vous utilisez PHP, essayez d'ajouter le code suivant au début du fichier php:
si vous utilisez localhost, essayez ceci:
header("Access-Control-Allow-Origin: *");
si vous utilisez des domaines externes tels que server, essayez ceci:
header("Access-Control-Allow-Origin: http://www.website.com");
pour le partage d'origine croisée, en-tête de série: 'Access-Control-Allow-Origin':'*';
Php: header('Access-Control-Allow-Origin':'*');
noeud: app.use('Access-Control-Allow-Origin':'*');
cela permettra de partager du contenu pour différents domaines.
en Python j'ai utilisé la Flask-CORS
bibliothèque avec un grand succès. Cela rend traiter avec CORS super facile et indolore. J'ai ajouté du code à partir de la documentation de la bibliothèque ci-dessous.
installation:
$ pip install -U flask-cors
exemple Simple qui permet des CORS pour tous les domaines sur 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 précis, voir la documentation. J'ai utilisé l'exemple simple ci-dessus pour contourner la question de CORS dans une application ionique je construis qui doit accéder à un serveur flasque séparé.