2016-08-03 50 views
10

Von dem, was ich gelesen habe über CORS, verstehe ich es funktionieren soll wie folgt:CORS: Warum sendet mein Browser keine OPTIONS Preflight Anfrage?

  1. Script auf einer Client-Seite eine Ressource von einem Server mit unterschiedlicher Herkunft zu zu holen versucht.
  2. Browser fängt diese Anfrage ab und macht zuerst Preflight OPTIONS Anfrage an die gleiche URL.
  3. Wenn Antwort auf diese Preflight-Anforderung enthält entsprechende Header (z Access-Control-Allow-Origin: *), Browser versteht es Haupt-Anfrage zu senden ist erlaubt und es tut.
  4. Antwort wird an das Clientskript zurückgegeben.

Ich habe einen Test für es wie folgt aufgebaut:

  • Server in beide gehen zu akzeptieren - GET und OPTIONS-Requests (geprüft cURL) - und Einstellung Access-Control-* Header in Reaktion
  • einfache HTML-Seite mit dem folgenden Skript drin ($ steht für jQuery) (von einem anderen Server auf einem anderen Port serviert):

    $.ajax({ 
        type: "GET", 
        crossDomain: true, 
        url: "http://local.site.com/endpoint, 
        success: function (data) { 
        alert(data); 
        }, 
        error: function (request, error) { 
        alert(error); 
        } 
    }); 
    

Wenn ich diese Methode aufrufen, aber ich sehe nur eine GET und keine Preflight-OPTIONS-Anforderung in der Registerkarte Netzwerk in beiden - Chrome 49 und Firefox 33.

Hier sind Details meiner GET-Anfrage von Chrome:

Accept:*/* 
Accept-Encoding:gzip, deflate, sdch 
Accept-Language:en-US,en;q=0.8,ru;q=0.6 
Connection:keep-alive 
Host:local.adform.com 
Origin:http://localhost:7500 
Referer:http://localhost:7500/test-page.html 
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36 

und entsprechende Antwort:

Access-Control-Allow-Headers:Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization 
Access-Control-Allow-Methods:POST, GET, OPTIONS, PUT, DELETE 
Access-Control-Allow-Origin:* 
Content-Length:2 
Content-Type:text/plain; charset=utf-8 
Date:Wed, 03 Aug 2016 10:53:19 GMT 

Irgendwelche Gedanken auf warum meinem Browser (n) nicht Preflight senden Anfrage?

+2

Preflight ist nicht immer möglich, weniger wahrscheinlich (wenn überhaupt?) Mit einem GET - siehe [Dokumentation] (https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests) wenn Preflight erforderlich ist –

+1

Siehe [this] (https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests) für weitere Informationen darüber, wann ein Browser eine Preflight-Anfrage absetzt. – robertklep

+0

@ JaromandaX: Danke für die Bemerkung. Wenn eine Preflight-Anforderung nicht immer erforderlich ist, was ist der (herkömmliche) Weg zur Überwindung der "source-origin" -Richtlinie? Das Szenario ist: Wir erstellen ein Skript, das in Websites von Drittanbietern integriert wird und uns _our_ cookies senden wird? Soweit ich weiß, wird ohne Preflight Request Browser keine Cookies an unsere Server senden, oder? – ffriend

Antwort

7

Wie von Kommentatoren darauf hingewiesen, mit GET Browser sendet nicht immer Preflight OPTIONS Anfrage. Wenn Preflight tatsächlich benötigt wird, besteht eine Möglichkeit, den Browser zum Senden zu veranlassen, darin, einen benutzerdefinierten Header zu setzen (z. B. "X-PINGOVER: pingpong" oder was auch immer). Beachten Sie, dass dieser Server auch diese Anfrage-Header durch Hinzufügen zu "Access-Control-Allow-Headers" Antwort Header erlauben sollte.


Mein zugrunde liegendes Ziel war Cookies mit Domain a.com zu Servern von a.com passieren, aber von einer Seite einer anderen Website (s) b.com (häufiger Anwendungsfall hierfür ist der Benutzer auf 3rd-Party-Websites Tracking) . Es stellt sich heraus, dass Cookies neben der Anfrage ein wenig mehr Arbeit beteiligt ist.

Auf der Client-Seite (d. H. In JavaScript) muss man domänenübergreifende Anfrage aktivieren und Zulassen von Anmeldeinformationen erlauben. Z.B.die folgende Anfrage mit jQuery für mich gearbeitet:

$.ajax({ 
    type: "GET", 
    url: "http://example.com", 
    xhrFields: { 
    withCredentials: true   // allow passing cookies 
    }, 
    crossDomain: true,    // force corss-domain request     
    success: function (data) { ... }, 
    error: function (request, error) { ... } 
}); 

Auf der Server-Seite eine 2-Antwort-Header setzen muss:

  • Access-Control-Allow-Credentials: true
  • Access-Control-Allow-Origin: <requester origin>

wo <requester origin> ist Protokoll + Host + Port einer Website, die einen Anruf ausgeführt hat. Beachten Sie, dass Generic * möglicherweise nicht in vielen Browsern funktioniert. Daher ist es sinnvoll, dass der Server Referer Header der Anforderung analysiert und mit einem bestimmten zulässigen Ursprung antwortet.

+0

Weitere Informationen finden Sie unter [MDN Preflight Request] (https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Preflighted_requests). – styfle

+0

Es ist wichtig zu beachten, dass Ihr Server "X-PINGOVER" möglicherweise nicht als Kopfzeile erwartet und es möglicherweise einen Fehler zurückgibt. Um dies zu beheben, schließen Sie in Ihrem Server-Code, in dem Sie den Wert von 'Access-Control-Allow-Headers' setzen, 'X-PINGOVER' ein – user2023861