Entschlüsseln Sie die Geheimnisse von CORS (Cross-Origin Resource Sharing) und lernen Sie, wie Sie domainübergreifende Anfragen in Ihren Webanwendungen sicher aktivieren. Dieser umfassende Leitfaden deckt alles von den Grundlagen bis zu fortgeschrittenen Konfigurationen ab und gewährleistet eine nahtlose und sichere Kommunikation zwischen verschiedenen Herkünften.
CORS entmystifiziert: Ein umfassender Leitfaden zu Cross-Origin Resource Sharing
Im heutigen vernetzten Web müssen Anwendungen häufig auf Ressourcen von verschiedenen Herkünften zugreifen. Hier kommt Cross-Origin Resource Sharing (CORS) ins Spiel. CORS ist ein entscheidender Sicherheitsmechanismus, der regelt, wie Webbrowser Anfragen von einer Herkunft (Domain, Protokoll und Port) an eine andere Herkunft behandeln. Das Verständnis von CORS ist für jeden Webentwickler unerlässlich, um sichere und funktionale Webanwendungen zu erstellen.
Was ist die Same-Origin-Policy?
Bevor wir uns mit CORS befassen, ist es wichtig, die Same-Origin-Policy (SOP) zu verstehen. Die SOP ist ein grundlegender Sicherheitsmechanismus, der in Webbrowsern implementiert ist. Ihr Zweck ist es, zu verhindern, dass bösartige Skripte auf einer Website auf sensible Daten auf einer anderen Website zugreifen. Eine Herkunft wird durch die Kombination aus Protokoll (z. B. HTTP oder HTTPS), Domain (z. B. example.com) und Portnummer (z. B. 80 oder 443) definiert. Zwei URLs gelten als von derselben Herkunft stammend, wenn sie dasselbe Protokoll, dieselbe Domain und denselben Port teilen.
Beispiel:
http://example.com/app1
undhttp://example.com/app2
- Gleiche Herkunft (gleiches Protokoll, Domain und Port)https://example.com/app1
undhttp://example.com/app1
- Unterschiedliche Herkunft (unterschiedliches Protokoll)http://example.com:8080/app1
undhttp://example.com/app1
- Unterschiedliche Herkunft (unterschiedlicher Port)http://sub.example.com/app1
undhttp://example.com/app1
- Unterschiedliche Herkunft (unterschiedliche Subdomain – wird als unterschiedliche Domain betrachtet)
Die SOP schränkt den Zugriff von Skripten auf Ressourcen von einer anderen Herkunft ein, es sei denn, es sind spezifische Maßnahmen wie CORS vorhanden, um dies zu erlauben.
Warum ist CORS notwendig?
Obwohl die Same-Origin-Policy für die Sicherheit unerlässlich ist, kann sie auch einschränkend sein. Viele moderne Webanwendungen sind darauf angewiesen, Daten von verschiedenen Servern abzurufen, wie z. B. von APIs oder Content Delivery Networks (CDNs). CORS bietet eine kontrollierte Möglichkeit, die SOP zu lockern und legitime herkunftsübergreifende Anfragen zu ermöglichen, während die Sicherheit gewahrt bleibt.
Stellen Sie sich ein Szenario vor, in dem eine Webanwendung, die auf http://example.com
gehostet wird, Daten von einem API-Server abrufen muss, der auf http://api.example.net
gehostet wird. Ohne CORS würde der Browser diese Anfrage aufgrund der SOP blockieren. CORS ermöglicht es dem API-Server, explizit anzugeben, welche Herkünfte auf seine Ressourcen zugreifen dürfen, sodass die Webanwendung korrekt funktionieren kann.
Wie CORS funktioniert: Die Grundlagen
CORS funktioniert über eine Reihe von HTTP-Headern, die zwischen dem Client (Browser) und dem Server ausgetauscht werden. Der Server verwendet diese Header, um den Browser darüber zu informieren, ob er auf die angeforderte Ressource zugreifen darf. Der wichtigste beteiligte HTTP-Header ist Access-Control-Allow-Origin
.
Szenario 1: Einfache Anfrage
Eine "einfache Anfrage" ist eine GET-, HEAD- oder POST-Anfrage, die bestimmte Kriterien erfüllt (z. B. wenn der Content-Type
-Header einer von application/x-www-form-urlencoded
, multipart/form-data
oder text/plain
ist). In diesem Fall sendet der Browser die Anfrage direkt an den Server, und der Server antwortet mit dem Access-Control-Allow-Origin
-Header.
Client-Anfrage (von http://example.com):
GET /data HTTP/1.1
Host: api.example.net
Origin: http://example.com
Server-Antwort (von http://api.example.net):
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Content-Type: application/json
{
"data": "Einige Daten vom Server"
}
In diesem Beispiel antwortet der Server mit Access-Control-Allow-Origin: http://example.com
, was anzeigt, dass Anfragen von http://example.com
erlaubt sind. Wenn die Herkunft in der Anfrage nicht mit dem Wert im Access-Control-Allow-Origin
-Header übereinstimmt (oder wenn der Header nicht vorhanden ist), blockiert der Browser die Antwort und verhindert, dass das clientseitige Skript auf die Daten zugreift.
Szenario 2: Preflight-Request (für komplexe Anfragen)
Bei komplexeren Anfragen, wie z. B. solchen, die HTTP-Methoden wie PUT oder DELETE verwenden oder solche mit benutzerdefinierten Headern, führt der Browser eine "Preflight"-Anfrage mit der HTTP-Methode OPTIONS durch. Diese Preflight-Anfrage bittet den Server um Erlaubnis, bevor die eigentliche Anfrage gesendet wird. Der Server antwortet mit Headern, die angeben, welche Methoden, Header und Herkünfte erlaubt sind.
Client-Preflight-Anfrage (von http://example.com):
OPTIONS /data HTTP/1.1
Host: api.example.net
Origin: http://example.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
Server-Antwort (von http://api.example.net):
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Access-Control-Allow-Methods: GET, PUT, DELETE
Access-Control-Allow-Headers: X-Custom-Header, Content-Type
Access-Control-Max-Age: 3600
Erklärung der Header:
Access-Control-Allow-Origin: http://example.com
- Zeigt an, dass Anfragen vonhttp://example.com
erlaubt sind.Access-Control-Allow-Methods: GET, PUT, DELETE
- Gibt die für herkunftsübergreifende Anfragen erlaubten HTTP-Methoden an.Access-Control-Allow-Headers: X-Custom-Header, Content-Type
- Listet die erlaubten benutzerdefinierten Header in der eigentlichen Anfrage auf.Access-Control-Max-Age: 3600
- Gibt die Dauer (in Sekunden) an, für die die Preflight-Antwort vom Browser zwischengespeichert werden kann. Dies hilft, die Anzahl der Preflight-Anfragen zu reduzieren.
Wenn die Preflight-Antwort des Servers anzeigt, dass die Anfrage erlaubt ist, fährt der Browser mit der eigentlichen Anfrage fort. Andernfalls blockiert der Browser die Anfrage.
Eigentliche Client-Anfrage (von http://example.com):
PUT /data HTTP/1.1
Host: api.example.net
Origin: http://example.com
X-Custom-Header: some-value
Content-Type: application/json
{
"data": "Einige zu aktualisierende Daten"
}
Server-Antwort (von http://api.example.net):
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Content-Type: application/json
{
"status": "Daten erfolgreich aktualisiert"
}
Gängige CORS-Header
Hier ist eine Aufschlüsselung der wichtigsten CORS-Header, die Sie verstehen müssen:
Access-Control-Allow-Origin
: Dieser Header ist der grundlegendste. Er gibt die Herkunft(en) an, die auf die Ressource zugreifen dürfen. Mögliche Werte sind:- Eine spezifische Herkunft (z. B.
http://example.com
). *
(Wildcard): Dies erlaubt Anfragen von jeder Herkunft. Mit Vorsicht verwenden, da dies die Sicherheit gefährden kann, wenn sensible Daten beteiligt sind. Es sollte in Produktionsumgebungen generell vermieden werden.
- Eine spezifische Herkunft (z. B.
Access-Control-Allow-Methods
: Dieser Header gibt die HTTP-Methoden (z. B. GET, POST, PUT, DELETE) an, die für herkunftsübergreifende Anfragen erlaubt sind. Er wird in der Preflight-Antwort verwendet.Access-Control-Allow-Headers
: Dieser Header listet die benutzerdefinierten Header auf, die in herkunftsübergreifenden Anfragen erlaubt sind. Er wird ebenfalls in der Preflight-Antwort verwendet.Access-Control-Allow-Credentials
: Dieser Header gibt an, ob der Server erlaubt, dass Anmeldeinformationen (z. B. Cookies, Autorisierungs-Header) in herkunftsübergreifende Anfragen aufgenommen werden. Er sollte auftrue
gesetzt werden, wenn Sie Anmeldeinformationen senden müssen. Auf der Client-Seite müssen Sie auchwithCredentials = true
für das XMLHttpRequest-Objekt setzen.Access-Control-Expose-Headers
: Standardmäßig stellen Browser clientseitigen Skripten nur eine begrenzte Anzahl von Antwort-Headern zur Verfügung (z. B.Cache-Control
,Content-Language
,Content-Type
,Expires
,Last-Modified
,Pragma
). Wenn Sie andere Header verfügbar machen möchten, müssen Sie sie imAccess-Control-Expose-Headers
-Header auflisten.Access-Control-Max-Age
: Dieser Header gibt die maximale Zeit (in Sekunden) an, die ein Browser die Preflight-Anfrage zwischenspeichern kann. Ein längerer Wert reduziert die Anzahl der Preflight-Anfragen und verbessert die Leistung.
CORS in verschiedenen serverseitigen Sprachen
Die Implementierung von CORS beinhaltet typischerweise die Konfiguration Ihrer serverseitigen Anwendung, um die entsprechenden CORS-Header zu senden. Hier sind Beispiele, wie dies in verschiedenen Sprachen und Frameworks gemacht wird:
Node.js mit Express
Sie können das cors
-Middleware-Paket verwenden:
const express = require('express');
const cors = require('cors');
const app = express();
// CORS für alle Herkünfte aktivieren (IN PRODUKTIVUMGEBUNGEN MIT VORSICHT VERWENDEN)
app.use(cors());
// Alternativ, CORS für spezifische Herkünfte konfigurieren
// app.use(cors({
// origin: 'http://example.com'
// }));
app.get('/data', (req, res) => {
res.json({ message: 'Dies ist CORS-fähig für alle Herkünfte!' });
});
app.listen(3000, () => {
console.log('Server läuft auf Port 3000');
});
Python mit Flask
Sie können die Flask-CORS
-Erweiterung verwenden:
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
# Alternativ, CORS für spezifische Herkünfte konfigurieren
# CORS(app, resources={r"/api/*": {"origins": "http://example.com"}})
@app.route("/data")
def hello():
return {"message": "Dies ist CORS-fähig für alle Herkünfte!"}
if __name__ == '__main__':
app.run(debug=True)
Java mit Spring Boot
Sie können CORS in Ihrer Spring Boot-Anwendung mithilfe von Annotationen oder Konfigurationsklassen konfigurieren:
Verwendung von Annotationen:
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@CrossOrigin(origins = "http://example.com") // Anfragen von http://example.com erlauben
public class DataController {
@GetMapping("/data")
public String getData() {
return "Dies ist CORS-fähig für http://example.com!";
}
}
Verwendung von Konfiguration:
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/data")
.allowedOrigins("http://example.com") // Anfragen von http://example.com erlauben
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*");
}
}
PHP
"Dies ist CORS-fähig für http://example.com!");
echo json_encode($data);
?>
CORS und Sicherheitsaspekte
Während CORS herkunftsübergreifende Anfragen ermöglicht, ist es entscheidend, es sicher zu implementieren. Hier sind einige wichtige Überlegungen:
- Vermeiden Sie die Verwendung von
*
fürAccess-Control-Allow-Origin
in der Produktion: Dies erlaubt Anfragen von jeder Herkunft, was ein Sicherheitsrisiko darstellen kann. Geben Sie stattdessen explizit die Herkünfte an, die auf Ihre Ressourcen zugreifen dürfen. - Validieren Sie den
Origin
-Header auf der Serverseite: Auch wenn Sie ein Framework verwenden, das die CORS-Konfiguration handhabt, ist es eine gute Praxis, denOrigin
-Header auf der Serverseite zu validieren, um sicherzustellen, dass die Anfrage von einer erwarteten Herkunft kommt. - Seien Sie vorsichtig mit
Access-Control-Allow-Credentials
: Wenn Sie Anmeldeinformationen (z. B. Cookies, Autorisierungs-Header) verwenden, stellen Sie sicher, dass SieAccess-Control-Allow-Credentials: true
auf der Serverseite undwithCredentials = true
auf der Client-Seite setzen. Beachten Sie jedoch, dass die Verwendung vonAccess-Control-Allow-Origin: *
nicht erlaubt ist, wennAccess-Control-Allow-Credentials
auftrue
gesetzt ist. Sie müssen die erlaubten Herkünfte explizit angeben. - Konfigurieren Sie
Access-Control-Allow-Methods
undAccess-Control-Allow-Headers
ordnungsgemäß: Erlauben Sie nur die HTTP-Methoden und Header, die für die korrekte Funktion Ihrer Anwendung notwendig sind. Dies hilft, die Angriffsfläche zu reduzieren. - Verwenden Sie HTTPS: Verwenden Sie immer HTTPS für Ihre Webanwendungen und APIs, um Daten während der Übertragung zu schützen.
Fehlerbehebung bei CORS-Problemen
CORS-Probleme können frustrierend zu debuggen sein. Hier sind einige häufige Probleme und wie man sie löst:
- "No 'Access-Control-Allow-Origin' header is present on the requested resource": Dies ist der häufigste CORS-Fehler. Er bedeutet, dass der Server den
Access-Control-Allow-Origin
-Header in seiner Antwort nicht sendet. Überprüfen Sie Ihre serverseitige Konfiguration, um sicherzustellen, dass der Header korrekt gesendet wird. - "Response to preflight request doesn't pass access control check: It does not have HTTP ok status": Dieser Fehler zeigt an, dass die Preflight-Anfrage fehlgeschlagen ist. Dies kann passieren, wenn der Server nicht für die Verarbeitung von OPTIONS-Anfragen konfiguriert ist oder wenn die Header
Access-Control-Allow-Methods
oderAccess-Control-Allow-Headers
nicht korrekt konfiguriert sind. - "The value of the 'Access-Control-Allow-Origin' header in the response is not equal to the origin in the request": Dieser Fehler bedeutet, dass die Herkunft in der Anfrage nicht mit dem Wert im
Access-Control-Allow-Origin
-Header übereinstimmt. Stellen Sie sicher, dass der Server die korrekte Herkunft in der Antwort sendet. - Browser-Caching: Manchmal können Browser CORS-Antworten zwischenspeichern, was zu unerwartetem Verhalten führen kann. Versuchen Sie, den Cache Ihres Browsers zu leeren oder einen anderen Browser zu verwenden, um zu sehen, ob das Problem dadurch behoben wird. Sie können auch den
Access-Control-Max-Age
-Header verwenden, um zu steuern, wie lange der Browser die Preflight-Antwort zwischenspeichert.
Debugging-Werkzeuge:
- Browser-Entwicklertools: Verwenden Sie die Entwicklertools des Browsers (normalerweise durch Drücken von F12 aufrufbar), um die Netzwerkanfragen und -antworten zu inspizieren. Achten Sie auf CORS-bezogene Header und Fehlermeldungen.
- Online-CORS-Prüfer: Es gibt Online-Tools, die Ihnen helfen können, Ihre CORS-Konfiguration zu testen. Diese Tools senden eine Anfrage an Ihren Server und analysieren die Antwort-Header, um potenzielle Probleme zu identifizieren.
Fortgeschrittene CORS-Szenarien
Obwohl die grundlegenden CORS-Konzepte relativ einfach sind, gibt es einige fortgeschrittenere Szenarien zu berücksichtigen:
- CORS mit Subdomains: Wenn Sie Anfragen von mehreren Subdomains (z. B.
app1.example.com
,app2.example.com
) erlauben müssen, können Sie nicht einfach eine Wildcard wie*.example.com
imAccess-Control-Allow-Origin
-Header verwenden. Stattdessen müssen Sie denAccess-Control-Allow-Origin
-Header dynamisch basierend auf demOrigin
-Header in der Anfrage generieren. Denken Sie daran, die Herkunft gegen eine Whitelist erlaubter Subdomains zu validieren, um Sicherheitslücken zu vermeiden. - CORS mit mehreren Herkünften: Wenn Sie Anfragen von mehreren spezifischen Herkünften erlauben müssen, können Sie nicht mehrere Herkünfte im
Access-Control-Allow-Origin
-Header angeben (z. B.Access-Control-Allow-Origin: http://example.com, http://another.com
ist ungültig). Stattdessen müssen Sie denAccess-Control-Allow-Origin
-Header dynamisch basierend auf demOrigin
-Header in der Anfrage generieren. - CORS und CDNs: Wenn Sie ein CDN verwenden, um Ihre API bereitzustellen, müssen Sie das CDN so konfigurieren, dass es den
Origin
-Header an Ihren Ursprungsserver weiterleitet und denAccess-Control-Allow-Origin
-Header korrekt zwischenspeichert. Konsultieren Sie die Dokumentation Ihres CDN-Anbieters für spezifische Anweisungen.
CORS Best Practices
Um eine sichere und effiziente CORS-Implementierung zu gewährleisten, befolgen Sie diese Best Practices:
- Prinzip der geringsten Rechte (Principle of Least Privilege): Erlauben Sie nur den minimalen Satz von Herkünften, Methoden und Headern, die für die korrekte Funktion Ihrer Anwendung notwendig sind.
- Regelmäßige Überprüfung der CORS-Konfiguration: Überprüfen Sie Ihre CORS-Konfiguration regelmäßig, während sich Ihre Anwendung weiterentwickelt, um sicherzustellen, dass sie immer noch angemessen und sicher ist.
- Verwenden Sie ein Framework oder eine Bibliothek: Nutzen Sie bestehende Frameworks oder Bibliotheken, die eine integrierte CORS-Unterstützung bieten. Dies kann die Implementierung vereinfachen und das Fehlerrisiko verringern.
- Überwachung auf CORS-Verletzungen: Implementieren Sie eine Überwachung, um potenzielle CORS-Verletzungen zu erkennen und darauf zu reagieren.
- Bleiben Sie auf dem Laufenden: Halten Sie sich über die neuesten CORS-Spezifikationen und Sicherheitsempfehlungen auf dem Laufenden.
Fazit
CORS ist ein entscheidender Sicherheitsmechanismus, der kontrollierte herkunftsübergreifende Anfragen in Webanwendungen ermöglicht. Das Verständnis, wie CORS funktioniert und wie man es richtig konfiguriert, ist für jeden Webentwickler unerlässlich. Indem Sie die in diesem umfassenden Leitfaden beschriebenen Richtlinien und Best Practices befolgen, können Sie sichere und funktionale Webanwendungen erstellen, die nahtlos mit Ressourcen von verschiedenen Herkünften interagieren.
Denken Sie daran, die Sicherheit immer an erste Stelle zu setzen und übermäßig freizügige CORS-Konfigurationen zu vermeiden. Indem Sie die Sicherheitsauswirkungen Ihrer CORS-Einstellungen sorgfältig abwägen, können Sie Ihre Anwendungen und Daten vor unbefugtem Zugriff schützen.
Wir hoffen, dieser Leitfaden hat Ihnen geholfen, CORS zu entmystifizieren. Viel Spaß beim Programmieren!