Ein kurzer Leitfaden für CORS

Eine Einführung in Cross-Origin Resource Sharing, die Art und Weise, wie Clients und Server kommunizieren können, auch wenn sie sich nicht in derselben Domäne befinden

Cors

Eine im Browser ausgeführte JavaScript-Anwendung kann normalerweise nur auf HTTP-Ressourcen in derselben Domäne (Herkunft) zugreifen, in der sie bereitgestellt wird.

Das Laden von Bildern oder Skripten / Stilen funktioniert immer, XHR- und Fetch-Aufrufe an einen anderen Server schlagen jedoch fehl, es sei denn, dieser Server implementiert eine Möglichkeit, diese Verbindung zuzulassen.

Dieser Weg wird als CORS, Cross-Origin Resource Sharingbezeichnet..

Auch das Laden von Webfonts mit@font-face hat standardmäßig dieselbe Richtlinie und andere weniger beliebte Dinge (wie WebGL-Texturen und drawImage Ressourcen, die in die Canvas-API geladen werden).

Eine sehr wichtige Sache, die CORS benötigt, sind ES Modules, die kürzlich in modernen Browsern eingeführt wurden.

Wenn Sie auf dem Server keine CORS-Richtlinie eingerichtet haben, die Drittherstellern dienen kann, schlägt die Anforderung fehl.

Beispiel holen:

Fehler beim Abrufen aufgrund der CORS-Richtlinie

XHR-Beispiel:

Die XHR-Anforderung ist aufgrund der CORS-Richtlinie fehlgeschlagen

Über- Origin-Ressource schlägt fehl, wenn

  • auf eine andere Domain
  • zu einer anderen Subdomain
  • zu einem anderen Hafen
  • zu einem anderen Protokoll
  • und es dient Ihrer Sicherheit, um zu
  • verhindern, dass bösartige Benutzer die
  • Webplattform ausnutzen.
  • Wenn Sie jedoch sowohl den Server als auch den Client steuern, haben Sie alle guten Gründe, um zuzulassen, dass sie miteinander sprechen.

    Wie?

    Das hängt von Ihrem serverseitigen Stack ab.

    Browser-Unterstützung

    Ziemlich gut (im Grunde alle außer IE <10):

    CORS Browser-Unterstützung

    Beispiel mit Express

    Wenn Sie Node.js und Express als Framework verwenden, verwenden Sie das CORS-Middleware-Paket.

    Hier ist eine einfache Implementierung eines Express Node.js server:

    const express = require('express')
    const app = express()
    app.get('/without-cors', (req, res, next) => {
      res.json({ msg: '???? no CORS, no party!' })
    })
    const server = app.listen(3000, () => {
      console.log('Listening on port %s', server.address().port)
    })
    

    Wenn Sie mit einer Abrufanforderung aus einem anderen Ursprung auf / withoutcors klicken, wird das CORS-Problem aufgeworfen. Sie müssen lediglich das oben verlinkte cors-Paket anfordern und es als Middleware-Funktion an einen Endpoint-Request-Handler übergeben, um das Problem zu lösen.

    const express = require('express')
    const cors = require('cors')
    const app = express()
    
    app.get('/with-cors', cors(), (req, res, next) => {
      res.json({ msg: 'WHOAH with CORS it works! ???? ????' })
    })
    / * der Rest der App * /
    

    ein einfaches Glitch-Beispiel Hier arbeitet der Clientund hier ist der Code: https://glitch.com/edit/#!/flavio-cors-client.

    Dies ist der Node.js Express-Server: https://glitch.com/edit/#!/flaviocopes-cors-example-express

    Beachten Sie, dass die Anforderung, die fehlgeschlagen ist, weil sie die CORS-Überschriften nicht korrekt verarbeitet, weiterhin empfangen wird, wie Sie in der Anzeige "Netzwerk" sehen können, in der Sie die vom Server gesendete Nachricht finden:

    No response from CORS

    Keine Antwort von CORS

    Erlaube nur bestimmte Ursprünge In diesem Beispiel gibt es jedoch ein Problem: JEDE Anfrage wird vom Server als Cross-Origin akzeptiert.

    Wie Sie in der Anzeige "Netzwerk" sehen können, hat die übergebene Anforderung einen Antwortheader access-control-allow-origin: *:

    Der CORS-Antwortheader

    Sie müssen den Server so konfigurieren, dass er nur einen Ursprung zulässt und alle anderen blockiert. Wenn Sie dieselbe cors Node-Bibliothek verwenden, gehen Sie wie folgt vor:

    const cors = require('cors')
    const corsOptions = {
      origin: 'https://yourdomain.com'
    }
    app.get('/products/:id', cors(corsOptions), (req, res, next) => {
      //...
    })
    

    Sie können auch mehr servieren:

    const whitelist = ['http://example1.com', 'http://example2.com']
    const corsOptions = {
      origin: function(origin, callback) {
        if (whitelist.indexOf(origin) !== -1) {
          callback(null, true)
        } else {
          callback(new Error('Not allowed by CORS'))
        }
      }
    }
    

    Preflight

    Es gibt einige Anforderungen, die auf "einfache" Weise behandelt werden. Alle GET-Anforderungen gehören zu dieser Gruppe.

    Auch einige POST- und HEAD-Requests tun dies ebenfalls.

    POST-Anforderungen befinden sich ebenfalls in dieser Gruppe, wenn sie die Anforderung der Verwendung eines Inhalts- Art der

    Alle anderen Anforderungen müssen eine Phase vor der Genehmigung durchlaufen, die als Preflight bezeichnet wird. Der Browser prüft anhand einer Anforderung von OPTIONS, ob er zur Ausführung einer Aktion berechtigt ist. Eine Preflight-Anforderung enthält einige Header, die der Server zum Überprüfen von Berechtigungen verwendet (irrelevante Felder werden weggelassen):

    OPTIONS /the/resource/you/request
    Access-Control-Request-Method: POST
    Access-Control-Request-Headers: origin, x-requested-with, accept
    Origin: https://your-origin.com
    

    Der Server antwortet folgendermaßen (irrelevante Felder weggelassen):

    HTTP/1.1 200 OK
    Access-Control-Allow-Origin: https://your-origin.com
    Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE
    

    Wir haben nach POST gesucht, der Server sagt uns jedoch, dass wir auch andere HTTP-Anforderungstypen für diese bestimmte Ressource ausgeben können. Dem Knoten folgen. js Express-Beispiel oben, der Server muss auch die Anforderung OPTIONS verarbeiten:

    var express = require('express')
    var cors = require('cors')
    var app = express()
    
    //allow OPTIONS on just one resource
    app.options('/the/resource/you/request', cors())
    
    //allow OPTIONS on all resources
    app.options('*', cors())
    

    Deprecated: Directive 'allow_url_include' is deprecated in Unknown on line 0