Frage Wie funktioniert Access-Control-Allow-Origin-Header?


Anscheinend habe ich seine Semantik völlig falsch verstanden. Ich dachte an so etwas:

  1. Ein Client lädt den JavaScript-Code MyCode.js von http: // siteA - der Ursprung.
  2. Der Antwortheader von MyCode.js enthält Zugriffssteuerung-Erlauben-Ursprung: http: // SiteB, was meiner Meinung nach bedeutete, dass MyCode.js Cross-Origin-Verweise auf die Site B erstellen durfte.
  3. Der Client löst einige Funktionen von MyCode.js aus, die wiederum Anforderungen an http: // siteB stellen, was trotz der querverweisenden Anforderungen in Ordnung sein sollte.

Nun, ich liege falsch. So funktioniert es überhaupt nicht. Also, ich habe gelesen Cross-Origin-Ressourcenfreigabe und versuchte zu lesen Quellenübergreifende Freigabe von Ressourcen in der w3c-Empfehlung

Eins ist sicher - ich verstehe immer noch nicht, wie ich diesen Header verwenden soll.

Ich habe die volle Kontrolle sowohl von Site A als auch von Site B. Wie aktiviere ich den JavaScript-Code, der von der Site A heruntergeladen wurde, um auf Ressourcen auf der Site B zuzugreifen, die diesen Header verwenden?

P.S.

Ich möchte JSONP nicht verwenden.


787
2018-05-17 13:23


Ursprung


Antworten:


Access-Control-Allow-Origin ist ein CORS-Header (Cross-Origin Resource Sharing).

Wenn Site A versucht, Inhalt von Site B abzurufen, kann Site B ein Access-Control-Allow-Origin Antwort-Header, um dem Browser mitzuteilen, dass der Inhalt dieser Seite für bestimmte Herkünfte zugänglich ist. (Ein Ursprung ist ein Domäne, plus ein Schema und eine Portnummer.) Die Seiten von Site B sind standardmäßig für andere Herkunft nicht zugänglich; Verwendung der Access-Control-Allow-Origin Kopfzeile öffnet eine Tür für den ursprungsübergreifenden Zugriff durch bestimmte anfragende Ursprünge.

Für jede Ressource / Seite, die Site B für Site A zugänglich machen möchte, sollte Site B ihre Seiten mit dem Response-Header bereitstellen:

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

Moderne Browser blockieren keine domainübergreifenden Anfragen. Wenn Site A eine Seite von Site B anfordert, ruft der Browser die angeforderte Seite tatsächlich ab auf der Netzwerkebene Überprüfen Sie, ob die Antwortheader Site A als zulässige Anfordererdomäne auflisten. Wenn Site B nicht angegeben hat, dass Site A auf diese Seite zugreifen darf, löst der Browser die URL aus XMLHttpRequestist es error Ereignis und verweigern Sie die Antwortdaten dem anfordernden JavaScript-Code.

Nicht einfache Anfragen

Was auf der Netzwerkebene passiert, kann sein leicht komplexer als oben erklärt. Wenn die Anfrage ein ist "nicht einfache" AnfrageDer Browser sendet zuerst eine datenlose "Preflight" -Option, um sicherzustellen, dass der Server die Anfrage akzeptiert. Eine Anfrage ist nicht einfach wenn beides (oder beide):

  • Verwenden eines anderen HTTP-Verbs als GET oder POST (z. B. PUT, DELETE)
  • Verwenden nicht einfacher Anforderungsheader; Die einzigen einfachen Anfragenheader sind:
    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type (Dies ist nur einfach, wenn sein Wert ist application/x-www-form-urlencoded, multipart/form-data, oder text/plain)

Wenn der Server auf das OPTIONS-Preflight mit entsprechenden Antwortheadern antwortet (Access-Control-Allow-Headers für nicht einfache Header, Access-Control-Allow-Methodsfür nicht-einfache Verben), die mit dem nicht-einfachen Verb und / oder nicht-einfachen Headern übereinstimmen, dann sendet der Browser die tatsächliche Anfrage.

Angenommen, Site A möchte eine PUT-Anforderung senden /somePagemit einem nicht einfachen Content-Type Wert von application/jsonwürde der Browser zuerst eine Preflight-Anfrage senden:

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

Beachten Sie, dass Access-Control-Request-Method und Access-Control-Request-Headers werden vom Browser automatisch hinzugefügt; Sie müssen sie nicht hinzufügen. Dieses OPTIONS-Preflight erhält die erfolgreichen Antwortheader:

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

Beim Senden der eigentlichen Anfrage (nach dem Preflight) ist das Verhalten identisch mit dem Umgang mit einer einfachen Anfrage. Mit anderen Worten, eine nicht einfache Anforderung, deren Preflight erfolgreich ist, wird wie eine einfache Anforderung behandelt (d. H. Der Server muss immer noch senden Access-Control-Allow-Origin wieder für die tatsächliche Antwort).

Der Browser sendet die eigentliche Anfrage:

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

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

Und der Server sendet ein Access-Control-Allow-Origin, so wie es für eine einfache Anfrage wäre:

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

Sehen Verstehen von XMLHttpRequest über CORS für ein wenig mehr Informationen über nicht einfache Anfragen.


1020
2018-05-17 13:33



Übergreifende Anfrage teilen - CORS (A.K.A. Domain-übergreifende AJAX-Anfrage) ist ein Problem, das die meisten Webentwickler nach Same-Origin-Policy kennen, Browser beschränken Client-JavaScript in einer Sicherheits-Sandbox, normalerweise kann JS nicht direkt mit einem Remote-Server aus einer anderen Domäne kommunizieren. In der Vergangenheit haben Entwickler viele knifflige Möglichkeiten geschaffen, um eine domänenübergreifende Ressourcenanfrage zu erreichen.

  1. Verwenden Sie Flash / Silverlight oder Server als Proxy für die Kommunikation mit Fernbedienung.
  2. JSON mit Polsterung (JSONP).
  3. Verbindet den Remote-Server in einem Iframe und kommuniziert über ein Fragment oder window.name, siehe Hier.

Diese kniffeligen Wege haben mehr oder weniger Probleme, zum Beispiel JSONP kann zu Sicherheitslücken führen, wenn Entwickler es einfach "evalieren", und oben # 3, obwohl es funktioniert, sollten beide Domänen einen strikten Vertrag zwischen einander aufbauen, weder flexibel noch elegant MEINER BESCHEIDENEN MEINUNG NACH:)

W3C hatte Cross-Origin Resource Sharing (CORS) als Standardlösung eingeführt, um einen sicheren, flexiblen und empfohlenen Standard zur Lösung dieses Problems zu bieten.

Der Mechanismus

Von einer höheren Ebene können wir einfach CORS als Vertrag zwischen einem Client-AJAX-Aufruf von Domäne A und einer Seite, die auf Domäne B gehostet wird, verstehen. Eine typische Cross-Origin-Anfrage / Antwort wäre:

DomainA AJAX-Anforderungsheader

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 Antwortheader

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

Die blauen Teile, die ich oben markiert habe, waren die Kerntatsachen, "Origin" -Aufforderungsheader "gibt an, woher die Ursprungsquellanfrage oder die Preflight-Anfrage stammt", der Antwortkopf "Access-Control-Allow-Origin" gibt an, dass diese Seite eine Fernanfrage ermöglicht DomainA (wenn der Wert "*" ist, können Remote-Anfragen von einer beliebigen Domäne akzeptiert werden).

Wie ich bereits erwähnt habe, hat W3 empfohlen, einen Browser zu implementieren "Preflight-Anfrage"Bevor die eigentliche Cross-Origin-HTTP-Anfrage abgeschickt wird, handelt es sich um ein HTTP OPTIONS anfordern:

OPTIONS DomainB.com/foo.aspx HTTP/1.1

Wenn foo.aspx das HTTP-Verb OPTIONS unterstützt, kann die Antwort wie folgt zurückgegeben werden:

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

Nur wenn die Antwort "Access-Control-Allow-Origin" enthält und ihr Wert "*" ist oder die Domäne enthält, die die CORS-Anfrage gesendet hat, sendet der Browser die aktuelle Cross-Domain-Anfrage und speichert das Ergebnis zwischen im "Preflight-Ergebnis-Cache".

Ich habe vor drei Jahren über CORS gebloggt: AJAX-übergreifende HTTP-Anfrage


102
2018-01-23 13:54



Die Frage ist ein bisschen zu alt, um sie zu beantworten, aber ich poste dies für einen späteren Hinweis auf diese Frage.

Gemäß Dies Mozilla Developer Network Artikel,

Eine Ressource macht a Ursprungsübergreifende HTTP-Anfrage wenn es eine Ressource von einer anderen Domäne oder einem anderen Port anfordert als derjenige, den die erste Ressource selbst bedient.

enter image description here

Ein HTML-Seite serviert von http://domain-a.com macht ein <img> src Anfrage für http://domain-b.com/image.jpg.
Viele Seiten im Web laden heute Ressourcen wie CSS-Stylesheets, Bilder und Skripte von getrennten Domains (also sollte es cool sein).

Richtlinie für gleiche Herkunft

Aus Sicherheitsgründen sind Browser eingeschränkt Ursprungs-HTTP Anfragen aus Skripten heraus initiiert.
Beispielsweise, XMLHttpRequest und Fetch Folge dem gleicher Herkunft.
Also, eine Webanwendung mit XMLHttpRequest oder Fetch konnte nur machen HTTP-Anfragen zu eine eigene Domain.

Ursprungsübergreifende Ressourcenteilung (CORS)

Um Webanwendungen zu verbessern, baten Entwickler Browseranbieter, domainübergreifende Anfragen zuzulassen.

Das Ursprungsübergreifende Ressourcenteilung (CORS) Mechanismus gibt Web-Server domänenübergreifende Zugriffskontrollen, die sichere domänenübergreifende Datenübertragungen ermöglichen.
Moderne Browser verwenden CORS in einem (n API-Container - sowie XMLHttpRequest oder Fetch - um das Risiko von Ursprungs-HTTP-Anfragen zu minimieren.

Wie funktioniert CORS (Access-Control-Allow-Origin Header)

Wikipedia:

Der CORS-Standard beschreibt neue HTTP-Header, die Browsern und Servern eine Möglichkeit bieten, Remote-URLs nur anzufordern, wenn sie über entsprechende Berechtigungen verfügen.

Obwohl einige Validierung und Autorisierung vom Server durchgeführt werden kann, Es liegt in der Regel in der Verantwortung des Browsers um diese Header zu unterstützen und die Einschränkungen, die sie auferlegen, zu beachten.

Beispiel

  1. Der Browser sendet die OPTIONS Anfrage mit einem Origin HTTP Header.

    Der Wert dieses Headers ist die Domäne, die die übergeordnete Seite bedient hat. Wenn eine Seite von http://www.example.com versucht, auf die Daten eines Benutzers zuzugreifen service.example.comwürde der folgende Anforderungsheader an gesendet service.example.com:

    Ursprung: http://www.beispiel.com

  2. Der Server bei service.example.com kann antworten mit:

    • Ein Access-Control-Allow-Origin (ACAO) -Header in seiner Antwort, die angibt, welche Ursprungsorte zulässig sind.
      Beispielsweise:

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

    • Eine Fehlerseite, wenn der Server die stammesübergreifende Anfrage nicht zulässt

    • Ein Access-Control-Allow-Origin (ACAO) Header mit einem Platzhalter, der alle Domains erlaubt:

      Access-Control-Allow-Origin: *


33
2018-03-05 06:39



Wenn Sie nur eine domänenübergreifende Anwendung testen möchten, in der der Browser Ihre Anfrage blockiert, können Sie Ihren Browser einfach im unsicheren Modus öffnen und Ihre Anwendung testen, ohne Ihren Code zu ändern und Ihren Code nicht unsicher zu machen. Von MAC OS aus können Sie dies über die Terminalzeile tun:

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

8
2018-02-22 16:32



1. Ein Client lädt JavaScript-Code MyCode.js von http: // siteA - der Ursprung.

Der Code, der den Download - Ihr HTML-Skript-Tag oder xhr von Javascript oder was auch immer - kam aus, sagen wir mal, http: // siteZ. Und wenn der Browser MyCode.js anfordert, sendet er einen Header von Origin: "Origin: http: // siteZ"Weil es sehen kann, dass Sie SiteA und SiteZ! = SiteA anfordern. (Sie können das nicht stoppen oder stören.)

2. Der Antwortheader von MyCode.js enthält Access-Control-Allow-Origin: http: // siteB, was meiner Meinung nach bedeutete, dass MyCode.js Cross-Origin-Verweise auf die Site B erstellen durfte.

Nein. Dies bedeutet, dass nur siteB diese Anfrage ausführen darf. Daher wird Ihre Anfrage für MyCode.js von siteZ stattdessen eine Fehlermeldung erhalten, und der Browser gibt Ihnen normalerweise nichts. Wenn Sie jedoch Ihren Server dazu bringen, stattdessen A-C-A-O: siteZ zurückzugeben, erhalten Sie MyCode.js. Oder wenn es '*' sendet, wird das funktionieren, das wird jeden hereinlassen. Oder wenn der Server immer die Zeichenkette vom Origin: Header sendet ... aber ... aus Sicherheitsgründen, wenn Sie Angst vor Hackern haben , Ihr Server sollte nur Ursprünge auf einer Auswahlliste zulassen, die diese Anfragen ausführen dürfen.

Dann kommt MyCode.js von SiteA. Wenn es Anfragen an SiteB stellt, sind sie alle Herkunftsort, der Browser sendet Origin: siteA, und siteB muss die SiteA nehmen, erkennen, dass sie auf der kurzen Liste der erlaubten Requester steht und A-C-A-O: siteA zurücksenden. Nur dann lässt der Browser Ihr Skript das Ergebnis dieser Anfragen erhalten.


6
2018-02-27 01:37



Ich arbeite mit Express 4 und Knoten 7.4 und eckig, ich hatte das gleiche Problem mir helfen, dies:
  a) Server-Seite: In der Datei app.js gebe ich Header für alle Antworten wie:

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();
 });  

das muss vor allem router haben.
Ich habe viele dieser Header gesehen:

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

aber ich brauche das nicht,
b) Client-Seite: In Send Ajax müssen Sie hinzufügen: "withCredentials: true", wie:

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

Viel Glück.


5
2018-02-06 08:19



Verwenden Reagieren und Axios, treten Sie dem Proxy-Link zur URL bei und fügen Sie den Header hinzu, wie unten gezeigt

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

Nur durch das Hinzufügen der Proxy-Link wird funktionieren, aber es kann auch Fehler für keinen Zugriff erneut auslösen. Daher besser, Kopfzeile wie unten gezeigt hinzuzufügen.

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

5
2017-10-16 15:53



Wenn Sie PHP verwenden, versuchen Sie, den folgenden Code am Anfang der PHP-Datei hinzuzufügen:

Wenn Sie localhost verwenden, versuchen Sie Folgendes:

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

Wenn Sie externe Domänen wie Server verwenden, versuchen Sie Folgendes:

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

4
2018-01-18 15:30



Stellen Sie für die gemeinsame Ursprungsfreigabe die Kopfzeile ein: 'Access-Control-Allow-Origin':'*';

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

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

Dadurch können Inhalte für verschiedene Domains freigegeben werden.


3
2017-11-28 02:39



Wann immer ich über CORS nachdenke, ist meine Intuition darüber, welche Seite die Header hostet, falsch, genau wie Sie es in Ihrer Frage beschrieben haben. Für mich ist es hilfreich, über den Zweck derselben Herkunftsrichtlinie nachzudenken.

Der Zweck der gleichen Ursprungsrichtlinie besteht darin, Sie vor schädlichem JavaScript auf siteA.com zu schützen, indem Sie auf private Informationen zugreifen, die Sie nur für siteB.com freigegeben haben. Ohne die gleiche Ursprungsrichtlinie kann JavaScript, das von den Autoren von siteA.com geschrieben wurde, Ihren Browser dazu veranlassen, Anfragen an siteB.com zu stellen, indem er Ihre Authentifizierungscookies für siteB.com verwendet. Auf diese Weise kann siteA.com die geheimen Informationen stehlen, die Sie mit siteA.com teilen.

Manchmal müssen Sie domänenübergreifend arbeiten, wo CORS ins Spiel kommt. CORS lockert die gleiche Herkunftsrichtlinie für domainA.com, indem es die Access-Control-Allow-Origin header, um andere Domains (domainB.com) aufzulisten, die JavaScript ausführen, das mit domainA.com interagieren kann.

Um zu verstehen, welche Domäne die CORS-Header bedienen soll, beachten Sie dies. Sie besuchen bosic.com, das einige JavaScript-Dateien enthält, mit denen versucht wird, eine domänenübergreifende Anfrage an mybank.com zu stellen. Es sollte an mybank.com, nicht an bosic.com liegen, um zu entscheiden, ob es CORS-Header setzt, die die gleichen Ursprungsrichtlinien lockern, sodass das JavaScript von inicial.com mit ihm interagieren kann. Wenn es für malicous.com möglich wäre, eigene CORS-Header zu setzen, die eigenen JavaScript-Zugriff auf mybank.com erlauben, würde dies die gleiche Herkunftsrichtlinie vollständig aufheben.

Ich denke, der Grund für meine schlechte Intuition ist der Standpunkt, den ich bei der Entwicklung einer Site habe. Es ist meine Website, mit allen meine JavaScript, deshalb macht es nichts böswilliges und es sollte auch so sein mich um anzugeben, welche anderen Websites meine JavaScript kann mit interagieren. Wenn ich tatsächlich darüber nachdenken sollte andere Websites JavaScript versucht, mit meiner Website zu interagieren und sollte ich CORS verwenden, um sie zuzulassen?


3
2018-01-28 18:47



In Python habe ich den Flask-CORS Bibliothek mit großem Erfolg. Es macht den Umgang mit CORS super einfach und schmerzlos. Ich habe etwas Code aus der Bibliotheksdokumentation hinzugefügt.

Installation:

$ pip install -U flask-cors

Einfaches Beispiel, das CORS für alle Domains auf allen Routen zulässt:

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

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

Genauere Beispiele finden Sie in der Dokumentation. Ich habe das einfache Beispiel oben verwendet, um das CORS-Problem in einer ionischen Anwendung, die ich erstelle, zu öffnen, die auf einen separaten Flaschenserver zugreifen muss.


1
2018-01-25 11:10