Aktivieren ursprungsübergreifender Anforderungen (CORS)
Hinweis
Dies ist nicht die neueste Version dieses Artikels. Um zur neuesten Version zu wechseln, verwenden Sie die ASP.NET Core-Versionsauswahl am oberen Rand des Inhaltsverzeichnisses.
Wenn die Auswahl in einem schmalen Browserfenster nicht sichtbar ist, verbreitern Sie das Fenster, oder wählen Sie die vertikalen Auslassungspunkte (⋮) >Inhaltsverzeichnis aus.
Von Rick Anderson und Kirk Larkin
In diesem Artikel erfahren Sie, wie Sie CORS in einer ASP.NET Core-App aktivieren.
Die Browsersicherheit verhindert, dass eine Webseite Anforderungen an eine andere Domäne als diejenige stellt, die die Webseite versorgt hat. Diese Einschränkung wird als Richtlinie des gleichen Ursprungs bezeichnet. Die Richtlinie des gleichen Ursprungs verhindert, dass eine schädliche Website sensible Daten von einer anderen Website liest. Manchmal möchten Sie möglicherweise anderen Websites erlauben, ursprungsübergreifende Anforderungen an Ihre App zu senden. Weitere Informationen finden Sie im Mozilla CORS-Artikel.
Ursprungsübergreifende Ressourcenfreigabe (Cross Origin Resource Sharing , CORS):
- Ist ein W3C-Standard, der es einem Server ermöglicht, die Richtlinie für denselben Ursprung zu lockern.
- Ist kein Sicherheitsfeature, CORS lockert die Sicherheit. Eine API ist nicht sicherer, indem CORS zugelassen wird. Weitere Informationen finden Sie unter Funktionsweise von CORS.
- Ermöglicht einem Server, einige ursprungsübergreifende Anforderungen explizit zuzulassen, während andere abgelehnt werden.
- Ist sicherer und flexibler als frühere Techniken wie JSONP.
Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)
Gleicher Ursprung
Zwei URLs haben denselben Ursprung, wenn sie über identische Schemas, Hosts und Ports verfügen (RFC 6454).
Diese beiden URLs haben denselben Ursprung:
https://example.com/foo.html
https://example.com/bar.html
Diese URLs haben andere Ursprünge als die vorherigen beiden URLs:
https://example.net
: Andere Domänehttps://www.example.com/foo.html
: Andere Unterdomänehttp://example.com/foo.html
: Anderes Schemahttps://example.com:9000/foo.html
: Anderer Port
Aktivieren von CORS
Es gibt drei Möglichkeiten, CORS zu aktivieren:
- In Middleware mit einer benannten OderStandardrichtlinie.
- Verwenden von Endpunktrouting.
- Mit dem [EnableCors] -Attribut.
Die Verwendung des [EnableCors]-Attributs mit einer benannten Richtlinie bietet die beste Kontrolle bei der Begrenzung von Endpunkten, die CORS unterstützen.
Warnung
UseCors muss in der richtigen Reihenfolge aufgerufen werden. Weitere Informationen finden Sie unter Middlewarereihenfolge. Muss z. UseCors
B. vor UseResponseCaching der Verwendung UseResponseCaching
von aufgerufen werden.
Jeder Ansatz wird in den folgenden Abschnitten erläutert.
CORS mit benannter Richtlinie und Middleware
CORS-Middleware verarbeitet ursprungsübergreifende Anforderungen. Der folgende Code wendet eine CORS-Richtlinie auf alle Endpunkte der App mit den angegebenen Ursprüngen an:
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
// services.AddResponseCaching();
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors(MyAllowSpecificOrigins);
app.UseAuthorization();
app.MapControllers();
app.Run();
Der vorangehende Code:
- Legt den Richtliniennamen auf fest
_myAllowSpecificOrigins
. Der Richtlinienname ist beliebig. - Ruft die UseCors Erweiterungsmethode auf und gibt die CORS-Richtlinie
_myAllowSpecificOrigins
an.UseCors
fügt die CORS-Middleware hinzu. Der Aufruf vonUseCors
muss nachUseRouting
, aber vorUseAuthorization
platziert werden. Weitere Informationen finden Sie unter Middlewarereihenfolge. - Aufrufe AddCors mit einem Lambdaausdruck. Das Lambda nimmt ein CorsPolicyBuilder -Objekt an. Konfigurationsoptionen wie
WithOrigins
werden weiter unten in diesem Artikel beschrieben. - Aktiviert die CORS-Richtlinie
_myAllowSpecificOrigins
für alle Controllerendpunkte. Informationen zum Anwenden einer CORS-Richtlinie auf bestimmte Endpunkte finden Sie unter Endpunktrouting . - Wenn Sie die Middleware für die Antwortzwischenspeicherung verwenden, rufen Sie UseCors vor auf UseResponseCaching.
Beim Endpunktrouting muss die CORS-Middleware für die Ausführung zwischen den Aufrufen von UseRouting
und UseEndpoints
konfiguriert werden.
Anweisungen zum Testen von Code ähnlich dem vorherigen Code finden Sie unter Testen von CORS .
Der AddCors Methodenaufruf fügt CORS-Dienste zum Dienstcontainer der App hinzu:
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
// services.AddResponseCaching();
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors(MyAllowSpecificOrigins);
app.UseAuthorization();
app.MapControllers();
app.Run();
Weitere Informationen finden Sie unter CORS-Richtlinienoptionen in diesem Dokument.
Die CorsPolicyBuilder Methoden können verkettet werden, wie im folgenden Code gezeigt:
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors(MyAllowSpecificOrigins);
app.UseAuthorization();
app.MapControllers();
app.Run();
Hinweis: Die angegebene URL darf keinen nachgestellten Schrägstrich (/
) enthalten. Wenn die URL mit /
beendet wird, gibt der Vergleich zurück false
, und es wird kein Header zurückgegeben.
Reihenfolge von UseCors und UseStaticFiles
UseStaticFiles
In der Regel wird vor UseCors
aufgerufen. Apps, die JavaScript zum websiteübergreifenden Abrufen statischer Dateien verwenden, müssen vor UseStaticFiles
aufrufenUseCors
.
CORS mit Standardrichtlinie und Middleware
Der folgende hervorgehobene Code aktiviert die CORS-Standardrichtlinie:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.MapControllers();
app.Run();
Der vorangehende Code wendet die CORS-Standardrichtlinie auf alle Controllerendpunkte an.
Aktivieren von Cors mit Endpunktrouting
Beim Endpunktrouting kann CORS auf Endpunktbasis mithilfe der RequireCors Erweiterungsmethoden aktiviert werden:
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
builder.Services.AddControllers();
builder.Services.AddRazorPages();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/echo",
context => context.Response.WriteAsync("echo"))
.RequireCors(MyAllowSpecificOrigins);
endpoints.MapControllers()
.RequireCors(MyAllowSpecificOrigins);
endpoints.MapGet("/echo2",
context => context.Response.WriteAsync("echo2"));
endpoints.MapRazorPages();
});
app.Run();
Für den Code oben gilt:
app.UseCors
aktiviert die CORS-Middleware. Da keine Standardrichtlinie konfiguriert wurde,app.UseCors()
wird CORS allein nicht aktiviert.- Die
/echo
Controllerendpunkte und ermöglichen ursprungsübergreifende Anforderungen mithilfe der angegebenen Richtlinie. - Die
/echo2
Pages-Endpunkte und Razor lassen ursprungsübergreifende Anforderungen nicht zu, da keine Standardrichtlinie angegeben wurde.
Das [DisableCors] -Attribut deaktiviert cors nicht , das durch Endpunktrouting mit RequireCors
aktiviert wurde.
Anweisungen zum Testen von Code finden Sie unter Testen von CORS mit dem [EnableCors]-Attribut und der RequireCors-Methode .
Aktivieren von CORS mit Attributen
Das Aktivieren von CORS mit dem [EnableCors]- Attribut und das Anwenden einer benannten Richtlinie nur auf die Endpunkte, die CORS erfordern, bietet die beste Steuerung.
Das Attribut [EnableCors] bietet eine Alternative zum globalen Anwenden von CORS. Das [EnableCors]
Attribut aktiviert CORS für ausgewählte Endpunkte und nicht für alle Endpunkte:
[EnableCors]
gibt die Standardrichtlinie an.[EnableCors("{Policy String}")]
gibt eine benannte Richtlinie an.
Das [EnableCors]
Attribut kann auf Folgendes angewendet werden:
- Razor Seite
PageModel
- Controller
- Controlleraktionsmethode
Mit dem [EnableCors]
-Attribut können verschiedene Richtlinien auf Controller, Seitenmodelle oder Aktionsmethoden angewendet werden. Wenn das [EnableCors]
Attribut auf einen Controller, ein Seitenmodell oder eine Aktionsmethode angewendet wird und CORS in middleware aktiviert ist, werden beide Richtlinien angewendet. Es wird davon abgeraten, Richtlinien zu kombinieren. Verwenden Sie die Schaltfläche [EnableCors]
Attribut oder Middleware, nicht beide in derselben App.
Der folgende Code wendet eine andere Richtlinie auf jede Methode an:
[Route("api/[controller]")]
[ApiController]
public class WidgetController : ControllerBase
{
// GET api/values
[EnableCors("AnotherPolicy")]
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { "green widget", "red widget" };
}
// GET api/values/5
[EnableCors("Policy1")]
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
return id switch
{
1 => "green widget",
2 => "red widget",
_ => NotFound(),
};
}
}
Der folgende Code erstellt zwei CORS-Richtlinien:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("Policy1",
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
options.AddPolicy("AnotherPolicy",
policy =>
{
policy.WithOrigins("http://www.contoso.com")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.MapControllers();
app.Run();
Für die beste Kontrolle der Begrenzung von CORS-Anforderungen:
- Verwenden Sie
[EnableCors("MyPolicy")]
mit einer benannten Richtlinie. - Definieren Sie keine Standardrichtlinie.
- Verwenden Sie kein Endpunktrouting.
Der Code im nächsten Abschnitt entspricht der vorherigen Liste.
Anweisungen zum Testen von Code, der dem vorherigen Code ähnelt, finden Sie unter Testen von CORS .
Deaktivieren von CORS
Das [DisableCors] -Attribut deaktiviert keine CORS, die durch Endpunktrouting aktiviert wurde.
Der folgende Code definiert die CORS-Richtlinie "MyPolicy"
:
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: "MyPolicy",
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com")
.WithMethods("PUT", "DELETE", "GET");
});
});
builder.Services.AddControllers();
builder.Services.AddRazorPages();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.UseEndpoints(endpoints => {
endpoints.MapControllers();
endpoints.MapRazorPages();
});
app.Run();
Der folgende Code deaktiviert CORS für die GetValues2
Aktion:
[EnableCors("MyPolicy")]
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public IActionResult Get() =>
ControllerContext.MyDisplayRouteInfo();
// GET api/values/5
[HttpGet("{id}")]
public IActionResult Get(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// PUT api/values/5
[HttpPut("{id}")]
public IActionResult Put(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// GET: api/values/GetValues2
[DisableCors]
[HttpGet("{action}")]
public IActionResult GetValues2() =>
ControllerContext.MyDisplayRouteInfo();
}
Der vorangehende Code:
- Aktiviert CORS nicht mit Endpunktrouting.
- Definiert keine CORS-Standardrichtlinie.
- Verwendet [EnableCors("MyPolicy")], um die CORS-Richtlinie
"MyPolicy"
für den Controller zu aktivieren. - Deaktiviert CORS für die
GetValues2
-Methode.
Anweisungen zum Testen des vorherigen Codes finden Sie unter Testen von CORS .
CORS-Richtlinienoptionen
In diesem Abschnitt werden die verschiedenen Optionen beschrieben, die in einer CORS-Richtlinie festgelegt werden können:
- Festlegen der zulässigen Ursprünge
- Festlegen der zulässigen HTTP-Methoden
- Festlegen der zulässigen Anforderungsheader
- Festlegen der verfügbar gemachten Antwortheader
- Anmeldeinformationen in ursprungsübergreifenden Anforderungen
- Festlegen der Preflight-Ablaufzeit
AddPolicy wird in Program.cs
aufgerufen. Für einige Optionen kann es hilfreich sein, zuerst den Abschnitt Funktionsweise von CORS zu lesen.
Festlegen der zulässigen Ursprünge
AllowAnyOrigin: Ermöglicht CORS-Anforderungen aus allen Ursprüngen mit einem beliebigen Schema (http
oder https
). AllowAnyOrigin
ist unsicher, da jede Website ursprungsübergreifende Anforderungen an die App stellen kann.
Hinweis
Die Angabe von AllowAnyOrigin
und AllowCredentials
ist eine unsichere Konfiguration und kann zu standortübergreifender Anforderungsfälschung führen. Der CORS-Dienst gibt eine ungültige CORS-Antwort zurück, wenn eine App mit beiden Methoden konfiguriert ist.
AllowAnyOrigin
wirkt sich auf Preflight-Anforderungen und den Access-Control-Allow-Origin
Header aus. Weitere Informationen finden Sie im Abschnitt Preflight-Anforderungen .
SetIsOriginAllowedToAllowWildcardSubdomains: Legt die IsOriginAllowed -Eigenschaft der Richtlinie als Funktion fest, die es Ursprüngen ermöglicht, einer konfigurierten Feldhalterdomäne bei der Bewertung zu entsprechen, ob der Ursprung zulässig ist.
var MyAllowSpecificOrigins = "_MyAllowSubdomainPolicy";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("https://*.example.com")
.SetIsOriginAllowedToAllowWildcardSubdomains();
});
});
builder.Services.AddControllers();
var app = builder.Build();
Festlegen der zulässigen HTTP-Methoden
- Ermöglicht jede HTTP-Methode:
- Wirkt sich auf Preflight-Anforderungen und den
Access-Control-Allow-Methods
Header aus. Weitere Informationen finden Sie im Abschnitt Preflight-Anforderungen .
Festlegen der zulässigen Anforderungsheader
Rufen WithHeaders Sie die zulässigen Header auf, um das Senden bestimmter Header in einer CORS-Anforderung als Autorenanforderungsheader zuzulassen:
using Microsoft.Net.Http.Headers;
var MyAllowSpecificOrigins = "_MyAllowSubdomainPolicy";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com")
.WithHeaders(HeaderNames.ContentType, "x-custom-header");
});
});
builder.Services.AddControllers();
var app = builder.Build();
Rufen Sie zum Zulassen aller Autorenanforderungsheader auf AllowAnyHeader:
var MyAllowSpecificOrigins = "_MyAllowSubdomainPolicy";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("https://*.example.com")
.AllowAnyHeader();
});
});
builder.Services.AddControllers();
var app = builder.Build();
AllowAnyHeader
wirkt sich auf Preflight-Anforderungen und den Access-Control-Request-Headers-Headers aus. Weitere Informationen finden Sie im Abschnitt Preflight-Anforderungen .
Eine Übereinstimmung der CORS-Middleware-Richtlinie mit bestimmten Headern, die durch WithHeaders
angegeben werden, ist nur möglich, wenn die gesendeten Access-Control-Request-Headers
Header genau mit den in WithHeaders
angegebenen Headern übereinstimmen.
Betrachten Sie beispielsweise eine App, die wie folgt konfiguriert ist:
app.UseCors(policy => policy.WithHeaders(HeaderNames.CacheControl));
CORS Middleware lehnt eine Preflight-Anforderung mit dem folgenden Anforderungsheader ab, da Content-Language
(HeaderNames.ContentLanguage) nicht in WithHeaders
aufgeführt ist:
Access-Control-Request-Headers: Cache-Control, Content-Language
Die App gibt eine Antwort mit 200 OK zurück, sendet die CORS-Header jedoch nicht zurück. Daher versucht der Browser die ursprungsübergreifende Anforderung nicht.
Festlegen der verfügbar gemachten Antwortheader
Standardmäßig macht der Browser nicht alle Antwortheader für die App verfügbar. Weitere Informationen finden Sie unter W3C Cross-Origin Resource Sharing (Terminologie): Einfacher Antwortheader.
Standardmäßig sind folgende Antwortheader verfügbar:
Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma
Die CORS-Spezifikation ruft diese Header als einfache Antwortheader auf. Rufen Sie folgendes auf WithExposedHeaders, um andere Header für die App verfügbar zu machen:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MyExposeResponseHeadersPolicy",
policy =>
{
policy.WithOrigins("https://*.example.com")
.WithExposedHeaders("x-custom-header");
});
});
builder.Services.AddControllers();
var app = builder.Build();
Anmeldeinformationen in ursprungsübergreifenden Anforderungen
Anmeldeinformationen erfordern eine spezielle Behandlung in einer CORS-Anforderung. Standardmäßig sendet der Browser keine Anmeldeinformationen mit einer ursprungsübergreifenden Anforderung. Anmeldeinformationen umfassen cookies- und HTTP-Authentifizierungsschemas. Um Anmeldeinformationen mit einer ursprungsübergreifenden Anforderung zu senden, muss der Client auf true
festlegenXMLHttpRequest.withCredentials
.
Direkte Verwendung XMLHttpRequest
:
var xhr = new XMLHttpRequest();
xhr.open('get', 'https://www.example.com/api/test');
xhr.withCredentials = true;
Verwenden von jQuery:
$.ajax({
type: 'get',
url: 'https://www.example.com/api/test',
xhrFields: {
withCredentials: true
}
});
Verwenden der Abruf-API:
fetch('https://www.example.com/api/test', {
credentials: 'include'
});
Der Server muss die Anmeldeinformationen zulassen. Um ursprungsübergreifende Anmeldeinformationen zuzulassen, rufen Sie folgendes auf AllowCredentials:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MyMyAllowCredentialsPolicy",
policy =>
{
policy.WithOrigins("http://example.com")
.AllowCredentials();
});
});
builder.Services.AddControllers();
var app = builder.Build();
Die HTTP-Antwort enthält einen Access-Control-Allow-Credentials
Header, der dem Browser mitteilt, dass der Server Anmeldeinformationen für eine ursprungsübergreifende Anforderung zulässt.
Wenn der Browser Anmeldeinformationen sendet, die Antwort aber keinen gültigen Access-Control-Allow-Credentials
Header enthält, macht der Browser die Antwort für die App nicht verfügbar, und die ursprungsübergreifende Anforderung schlägt fehl.
Das Zulassen von ursprungsübergreifenden Anmeldeinformationen ist ein Sicherheitsrisiko. Eine Website in einer anderen Domäne kann die Anmeldeinformationen eines angemeldeten Benutzers im Namen des Benutzers ohne Wissen des Benutzers an die App senden.
Die CORS-Spezifikation besagt auch, dass das Festlegen von Ursprüngen auf "*"
(alle Ursprünge) ungültig ist, wenn der Access-Control-Allow-Credentials
Header vorhanden ist.
Preflight-Anforderungen
Bei einigen CORS-Anforderungen sendet der Browser vor der eigentlichen Anforderung eine zusätzliche OPTIONS-Anforderung . Diese Anforderung wird als Preflight-Anforderung bezeichnet. Der Browser kann die Preflight-Anforderung überspringen, wenn alle folgenden Bedingungen erfüllt sind:
- Die Anforderungsmethode ist GET, HEAD oder POST.
- Die App legt keine anderen Anforderungsheader als
Accept
, ,Accept-Language
Content-Language
,Content-Type
oderLast-Event-ID
fest. - Falls festgelegt, weist der
Content-Type
Header einen der folgenden Werte auf:application/x-www-form-urlencoded
multipart/form-data
text/plain
Die Für die Clientanforderung festgelegte Regel für Anforderungsheader gilt für Header, die die App durch Aufrufen setRequestHeader
des XMLHttpRequest
-Objekts festlegt. Die CORS-Spezifikation ruft diese Header für Autorenanforderungsheader auf. Die Regel gilt nicht für Header, die der Browser festlegen kann, z User-Agent
. B. , Host
oder Content-Length
.
Die folgende Beispielantwort ähnelt der Preflight-Anforderung über die Schaltfläche [Test ablegen] im Abschnitt CORS testen dieses Dokuments.
General:
Request URL: https://cors3.azurewebsites.net/api/values/5
Request Method: OPTIONS
Status Code: 204 No Content
Response Headers:
Access-Control-Allow-Methods: PUT,DELETE,GET
Access-Control-Allow-Origin: https://cors1.azurewebsites.net
Server: Microsoft-IIS/10.0
Set-Cookie: ARRAffinity=8f8...8;Path=/;HttpOnly;Domain=cors1.azurewebsites.net
Vary: Origin
Request Headers:
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Access-Control-Request-Method: PUT
Connection: keep-alive
Host: cors3.azurewebsites.net
Origin: https://cors1.azurewebsites.net
Referer: https://cors1.azurewebsites.net/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0
Die Preflight-Anforderung verwendet die HTTP OPTIONS-Methode . Es kann die folgenden Header enthalten:
- Access-Control-Request-Method: Die HTTP-Methode, die für die tatsächliche Anforderung verwendet wird.
- Access-Control-Request-Headers: Eine Liste der Anforderungsheader, die die App für die tatsächliche Anforderung festlegt. Wie bereits erwähnt, enthält dies keine Header, die vom Browser festgelegt werden, z. B
User-Agent
. . - Access-Control-Allow-Methods
Wenn die Preflight-Anforderung abgelehnt wird, gibt die App eine 200 OK
Antwort zurück, legt aber die CORS-Header nicht fest. Daher versucht der Browser die ursprungsübergreifende Anforderung nicht. Ein Beispiel für eine verweigerte Preflight-Anforderung finden Sie im Abschnitt CORS-Test dieses Dokuments.
Bei Verwendung der F12-Tools zeigt die Konsolen-App je nach Browser einen Fehler ähnlich einem der folgenden an:
- Firefox: Cross-Origin Request Blockiert: Die gleiche Ursprungsrichtlinie lässt das Lesen der Remoteressource unter nicht zu
https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5
. (Grund: CORS-Anforderung war nicht erfolgreich). Weitere Informationen - Chromium basiert: Der Zugriff auf den Abruf von "https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5" vom Ursprung "https://cors3.azurewebsites.net" wurde durch die CORS-Richtlinie blockiert: Die Antwort auf eine Preflight-Anforderung besteht nicht über die Zugriffssteuerungsprüfung: Für die angeforderte Ressource ist kein "Access-Control-Allow-Origin"-Header vorhanden. Falls eine opake Antwort Ihre Anforderungen erfüllt, legen Sie den Modus der Anforderung auf 'no-cors' fest, um CORS für den Ressourcenabruf zu deaktivieren.
Um bestimmte Header zuzulassen, rufen Sie folgendes auf WithHeaders:
using Microsoft.Net.Http.Headers;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MyAllowHeadersPolicy",
policy =>
{
policy.WithOrigins("http://example.com")
.WithHeaders(HeaderNames.ContentType, "x-custom-header");
});
});
builder.Services.AddControllers();
var app = builder.Build();
Rufen Sie zum Zulassen aller Autorenanforderungsheader auf AllowAnyHeader:
using Microsoft.Net.Http.Headers;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MyAllowAllHeadersPolicy",
policy =>
{
policy.WithOrigins("https://*.example.com")
.AllowAnyHeader();
});
});
builder.Services.AddControllers();
var app = builder.Build();
Browser sind nicht konsistent, wenn sie festlegen Access-Control-Request-Headers
. Wenn einer der folgenden Aktionen zu beachten ist:
- Header sind auf alles andere als festgelegt.
"*"
- AllowAnyHeader wird aufgerufen: Schließen Sie mindestens
Accept
,Content-Type
undOrigin
sowie alle benutzerdefinierten Header ein, die Sie unterstützen möchten.
Code für automatische Preflight-Anforderungen
Wenn die CORS-Richtlinie angewendet wird:
- Global, indem Sie in
Program.cs
aufrufenapp.UseCors
. - Verwenden des -Attributs
[EnableCors]
.
ASP.NET Core antwortet auf die Preflight OPTIONS-Anforderung.
Im Abschnitt CORS-Test dieses Dokuments wird dieses Verhalten veranschaulicht.
[HttpOptions]-Attribut für Preflight-Anforderungen
Wenn CORS mit der entsprechenden Richtlinie aktiviert ist, reagiert ASP.NET Core in der Regel automatisch auf CORS-Preflight-Anforderungen.
Der folgende Code verwendet das [HttpOptions]- Attribut, um Endpunkte für OPTIONS-Anforderungen zu erstellen:
[Route("api/[controller]")]
[ApiController]
public class TodoItems2Controller : ControllerBase
{
// OPTIONS: api/TodoItems2/5
[HttpOptions("{id}")]
public IActionResult PreflightRoute(int id)
{
return NoContent();
}
// OPTIONS: api/TodoItems2
[HttpOptions]
public IActionResult PreflightRoute()
{
return NoContent();
}
[HttpPut("{id}")]
public IActionResult PutTodoItem(int id)
{
if (id < 1)
{
return BadRequest();
}
return ControllerContext.MyDisplayRouteInfo(id);
}
Anweisungen zum Testen des vorherigen Codes finden Sie unter Testen von CORS mit dem Attribut [EnableCors] und der RequireCors-Methode .
Festlegen der Preflight-Ablaufzeit
Der Access-Control-Max-Age
Header gibt an, wie lange die Antwort auf die Preflight-Anforderung zwischengespeichert werden kann. Rufen Sie zum Festlegen dieses Headers auf SetPreflightMaxAge:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MySetPreflightExpirationPolicy",
policy =>
{
policy.WithOrigins("http://example.com")
.SetPreflightMaxAge(TimeSpan.FromSeconds(2520));
});
});
builder.Services.AddControllers();
var app = builder.Build();
Aktivieren von CORS auf einem Endpunkt
Funktionsweise von CORS
In diesem Abschnitt wird beschrieben, was in einer CORS-Anforderung auf der Ebene der HTTP-Nachrichten geschieht.
- CORS ist kein Sicherheitsfeature. CORS ist ein W3C-Standard, der es einem Server ermöglicht, die Richtlinie desselben Ursprungs zu lockern.
- Beispielsweise kann ein böswilliger Akteur Cross-Site Scripting (XSS) für Ihre Website verwenden und eine websiteübergreifende Anforderung an seine CORS-fähige Website ausführen, um Informationen zu stehlen.
- Eine API ist nicht sicherer, indem CORS zugelassen wird.
- Es liegt am Client (Browser), CORS zu erzwingen. Der Server führt die Anforderung aus und gibt die Antwort zurück. Es ist der Client, der einen Fehler zurückgibt und die Antwort blockiert. Beispielsweise zeigt eines der folgenden Tools die Serverantwort an:
- Fiddler
- Postman
- .NET HttpClient
- Ein Webbrowser, indem Sie die URL in die Adressleiste eingeben.
- Es liegt am Client (Browser), CORS zu erzwingen. Der Server führt die Anforderung aus und gibt die Antwort zurück. Es ist der Client, der einen Fehler zurückgibt und die Antwort blockiert. Beispielsweise zeigt eines der folgenden Tools die Serverantwort an:
- Es ist eine Möglichkeit für einen Server, Browsern zu erlauben, eine ursprungsübergreifende XHR - oder Fetch-API-Anforderung auszuführen, die andernfalls verboten wäre.
- Browser ohne CORS können keine ursprungsübergreifenden Anforderungen ausführen. Vor CORS wurde ONP verwendet,JS um diese Einschränkung zu umgehen. JSONP verwendet nicht XHR, es verwendet das
<script>
-Tag, um die Antwort zu empfangen. Skripts dürfen ursprungsübergreifend geladen werden.
- Browser ohne CORS können keine ursprungsübergreifenden Anforderungen ausführen. Vor CORS wurde ONP verwendet,JS um diese Einschränkung zu umgehen. JSONP verwendet nicht XHR, es verwendet das
Mit der CORS-Spezifikation wurden mehrere neue HTTP-Header eingeführt, die ursprungsübergreifende Anforderungen ermöglichen. Wenn ein Browser CORS unterstützt, legt er diese Header automatisch für ursprungsübergreifende Anforderungen fest. Benutzerdefinierter JavaScript-Code ist nicht erforderlich, um CORS zu aktivieren.
Die SCHALTFLÄCHE PUT-Test im bereitgestellten Beispiel
Im Folgenden wird ein Beispiel für eine ursprungsübergreifende Anforderung von der Schaltfläche Wertetest an angezeigt https://cors1.azurewebsites.net/api/values
. Der Origin
Header:
- Stellt die Domäne des Standorts bereit, der die Anforderung stellt.
- Ist erforderlich und muss sich vom Host unterscheiden.
Allgemeine Header
Request URL: https://cors1.azurewebsites.net/api/values
Request Method: GET
Status Code: 200 OK
Antwortheader
Content-Encoding: gzip
Content-Type: text/plain; charset=utf-8
Server: Microsoft-IIS/10.0
Set-Cookie: ARRAffinity=8f...;Path=/;HttpOnly;Domain=cors1.azurewebsites.net
Transfer-Encoding: chunked
Vary: Accept-Encoding
X-Powered-By: ASP.NET
Anforderungsheader
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Host: cors1.azurewebsites.net
Origin: https://cors3.azurewebsites.net
Referer: https://cors3.azurewebsites.net/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0 ...
In OPTIONS
Anforderungen legt der Server den Header AntwortheaderAccess-Control-Allow-Origin: {allowed origin}
in der Antwort fest. Beispielsweise enthält das bereitgestellte Beispieldie SchaltflächenanforderungOPTIONS
löschen [EnableCors] die folgenden Header:
Allgemeine Header
Request URL: https://cors3.azurewebsites.net/api/TodoItems2/MyDelete2/5
Request Method: OPTIONS
Status Code: 204 No Content
Antwortheader
Access-Control-Allow-Headers: Content-Type,x-custom-header
Access-Control-Allow-Methods: PUT,DELETE,GET,OPTIONS
Access-Control-Allow-Origin: https://cors1.azurewebsites.net
Server: Microsoft-IIS/10.0
Set-Cookie: ARRAffinity=8f...;Path=/;HttpOnly;Domain=cors3.azurewebsites.net
Vary: Origin
X-Powered-By: ASP.NET
Anforderungsheader
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: DELETE
Connection: keep-alive
Host: cors3.azurewebsites.net
Origin: https://cors1.azurewebsites.net
Referer: https://cors1.azurewebsites.net/test?number=2
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0
In den vorherigen Antwortheadern legt der Server den Access-Control-Allow-Origin-Header in der Antwort fest. Der https://cors1.azurewebsites.net
Wert dieses Headers entspricht dem Origin
Header aus der Anforderung.
Wenn AllowAnyOrigin aufgerufen wird, wird der Access-Control-Allow-Origin: *
, der Feldhalterwert, zurückgegeben. AllowAnyOrigin
lässt jeden Ursprung zu.
Wenn die Antwort den Header nicht enthält Access-Control-Allow-Origin
, schlägt die ursprungsübergreifende Anforderung fehl. Insbesondere lässt der Browser die Anforderung nicht zu. Auch wenn der Server eine erfolgreiche Antwort zurückgibt, stellt der Browser die Antwort nicht für die Client-App zur Verfügung.
HTTP-Umleitung zu HTTPS verursacht ERR_INVALID_REDIRECT für die CORS-Preflight-Anforderung
Anforderungen an einen Endpunkt mithilfe von UseHttpsRedirection HTTP, die an HTTPS weitergeleitet werden, schlagen mit ERR_INVALID_REDIRECT on the CORS preflight request
fehl.
API-Projekte können HTTP-Anforderungen ablehnen, anstatt UseHttpsRedirection
Anforderungen an HTTPS umzuleiten.
CORS in IIS
Bei der Bereitstellung in IIS muss CORS vor der Windows-Authentifizierung ausgeführt werden, wenn der Server nicht für den anonymen Zugriff konfiguriert ist. Um dieses Szenario zu unterstützen, muss das IIS CORS-Modul installiert und für die App konfiguriert werden.
Testen von CORS
Der Beispieldownload enthält Code zum Testen von CORS. Informationen zum Herunterladen finden Sie hier. Das Beispiel ist ein API-Projekt mit Razor hinzugefügten Seiten:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: "MyPolicy",
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com",
"https://cors1.azurewebsites.net",
"https://cors3.azurewebsites.net",
"https://localhost:44398",
"https://localhost:5001")
.WithMethods("PUT", "DELETE", "GET");
});
});
builder.Services.AddControllers();
builder.Services.AddRazorPages();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.MapControllers();
app.MapRazorPages();
app.Run();
Warnung
WithOrigins("https://localhost:<port>");
sollte nur zum Testen einer Beispiel-App verwendet werden, die dem Downloadbeispielcode ähnelt.
Im Folgenden ValuesController
werden die Endpunkte für Tests bereitgestellt:
[EnableCors("MyPolicy")]
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public IActionResult Get() =>
ControllerContext.MyDisplayRouteInfo();
// GET api/values/5
[HttpGet("{id}")]
public IActionResult Get(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// PUT api/values/5
[HttpPut("{id}")]
public IActionResult Put(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// GET: api/values/GetValues2
[DisableCors]
[HttpGet("{action}")]
public IActionResult GetValues2() =>
ControllerContext.MyDisplayRouteInfo();
}
MyDisplayRouteInfo wird von dem NuGet-Paket Rick.Docs.Samples.RouteInfo bereitgestellt und zeigt Routeninformationen an.
Testen Sie den vorherigen Beispielcode mit einem der folgenden Ansätze:
- Verwenden Sie die bereitgestellte Beispiel-App unter https://cors3.azurewebsites.net/. Das Beispiel muss nicht heruntergeladen werden.
- Führen Sie das Beispiel mit
dotnet run
der Standard-URL von aushttps://localhost:5001
. - Führen Sie das Beispiel in Visual Studio aus, wobei der Port auf 44398 für eine URL von
https://localhost:44398
festgelegt ist.
Verwenden eines Browsers mit den F12-Tools:
Wählen Sie die Schaltfläche Werte aus, und überprüfen Sie die Header auf der Registerkarte Netzwerk .
Wählen Sie die Schaltfläche PUT-Test aus. Anweisungen zum Anzeigen der OPTIONS-Anforderung finden Sie unter Anzeigen von OPTIONS-Anforderungen . Der PUT-Test erstellt zwei Anforderungen, eine OPTIONS-Preflight-Anforderung und die PUT-Anforderung.
Wählen Sie die
GetValues2 [DisableCors]
Schaltfläche aus, um eine fehlerhafte CORS-Anforderung auszulösen. Wie im Dokument erwähnt, gibt die Antwort 200 erfolgreich zurück, aber die CORS-Anforderung wird nicht gestellt. Wählen Sie die Registerkarte Konsole aus, um den CORS-Fehler anzuzeigen. Je nach Browser wird ein Fehler ähnlich dem folgenden angezeigt:Der Zugriff auf
'https://cors1.azurewebsites.net/api/values/GetValues2'
den Abruf vom Ursprung'https://cors3.azurewebsites.net'
wurde durch die CORS-Richtlinie blockiert: Für die angeforderte Ressource ist kein "Access-Control-Allow-Origin"-Header vorhanden. Falls eine opake Antwort Ihre Anforderungen erfüllt, legen Sie den Modus der Anforderung auf 'no-cors' fest, um CORS für den Ressourcenabruf zu deaktivieren.
CORS-fähige Endpunkte können mit einem Tool wie curl, Fiddler oder Postman getestet werden. Bei Verwendung eines Tools muss sich der Ursprung der durch den Origin
Header angegebenen Anforderung von dem Host unterscheiden, der die Anforderung empfängt. Wenn die Anforderung nicht originsübergreifend ist, basierend auf dem Wert des Origin
Headers:
- Cors Middleware muss die Anforderung nicht verarbeiten.
- CORS-Header werden in der Antwort nicht zurückgegeben.
Der folgende Befehl verwendet curl
, um eine OPTIONS-Anforderung mit Informationen ausstellen zu können:
curl -X OPTIONS https://cors3.azurewebsites.net/api/TodoItems2/5 -i
Testen von CORS mit dem Attribut [EnableCors] und der RequireCors-Methode
Betrachten Sie den folgenden Code, der Endpunktrouting verwendet, um CORS pro Endpunkt zu aktivieren:RequireCors
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: "MyPolicy",
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com",
"https://cors1.azurewebsites.net",
"https://cors3.azurewebsites.net",
"https://localhost:44398",
"https://localhost:5001")
.WithMethods("PUT", "DELETE", "GET");
});
});
builder.Services.AddControllers();
builder.Services.AddRazorPages();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/echo",
context => context.Response.WriteAsync("echo"))
.RequireCors("MyPolicy");
endpoints.MapControllers();
endpoints.MapRazorPages();
});
app.Run();
Beachten Sie, dass nur der /echo
Endpunkt verwendet, RequireCors
um ursprungsübergreifende Anforderungen mithilfe der angegebenen Richtlinie zuzulassen. Die folgenden Controller aktivieren CORS mit dem Attribut [EnableCors].
Im Folgenden TodoItems1Controller
werden Endpunkte für Tests bereitgestellt:
[Route("api/[controller]")]
[ApiController]
public class TodoItems1Controller : ControllerBase
{
// PUT: api/TodoItems1/5
[HttpPut("{id}")]
public IActionResult PutTodoItem(int id) {
if (id < 1) {
return Content($"ID = {id}");
}
return ControllerContext.MyDisplayRouteInfo(id);
}
// Delete: api/TodoItems1/5
[HttpDelete("{id}")]
public IActionResult MyDelete(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// GET: api/TodoItems1
[HttpGet]
public IActionResult GetTodoItems() =>
ControllerContext.MyDisplayRouteInfo();
[EnableCors("MyPolicy")]
[HttpGet("{action}")]
public IActionResult GetTodoItems2() =>
ControllerContext.MyDisplayRouteInfo();
// Delete: api/TodoItems1/MyDelete2/5
[EnableCors("MyPolicy")]
[HttpDelete("{action}/{id}")]
public IActionResult MyDelete2(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
}
Testen Sie den vorherigen Code auf der Testseite des bereitgestellten Beispiels.
Die Schaltflächen Löschen [EnableCors] und GET [EnableCors] sind erfolgreich, da die Endpunkte Preflight-Anforderungen enthalten [EnableCors]
und darauf reagieren. Bei den anderen Endpunkten tritt ein Fehler auf. Die Get-Schaltfläche schlägt fehl, da JavaScript Folgendes sendet:
headers: {
"Content-Type": "x-custom-header"
},
Im Folgenden TodoItems2Controller
werden ähnliche Endpunkte bereitgestellt, aber expliziter Code zum Reagieren auf OPTIONS-Anforderungen:
[Route("api/[controller]")]
[ApiController]
public class TodoItems2Controller : ControllerBase
{
// OPTIONS: api/TodoItems2/5
[HttpOptions("{id}")]
public IActionResult PreflightRoute(int id)
{
return NoContent();
}
// OPTIONS: api/TodoItems2
[HttpOptions]
public IActionResult PreflightRoute()
{
return NoContent();
}
[HttpPut("{id}")]
public IActionResult PutTodoItem(int id)
{
if (id < 1)
{
return BadRequest();
}
return ControllerContext.MyDisplayRouteInfo(id);
}
// [EnableCors] // Not needed as OPTIONS path provided.
[HttpDelete("{id}")]
public IActionResult MyDelete(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// [EnableCors] // Warning ASP0023 Route '{id}' conflicts with another action route.
// An HTTP request that matches multiple routes results in an ambiguous
// match error.
[EnableCors("MyPolicy")] // Required for this path.
[HttpGet]
public IActionResult GetTodoItems() =>
ControllerContext.MyDisplayRouteInfo();
[HttpGet("{action}")]
public IActionResult GetTodoItems2() =>
ControllerContext.MyDisplayRouteInfo();
[EnableCors("MyPolicy")] // Required for this path.
[HttpDelete("{action}/{id}")]
public IActionResult MyDelete2(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
}
Testen Sie den vorherigen Code auf der Testseite des bereitgestellten Beispiels. Wählen Sie in der Dropdownliste Controllerdie Option Preflight und dann Controller festlegen aus. Alle CORS-Aufrufe der TodoItems2Controller
Endpunkte sind erfolgreich.
Zusätzliche Ressourcen
Von Rick Anderson und Kirk Larkin
In diesem Artikel erfahren Sie, wie Sie CORS in einer ASP.NET Core-App aktivieren.
Die Browsersicherheit verhindert, dass eine Webseite Anforderungen an eine andere Domäne als diejenige stellt, die die Webseite versorgt hat. Diese Einschränkung wird als Richtlinie des gleichen Ursprungs bezeichnet. Die Richtlinie des gleichen Ursprungs verhindert, dass eine schädliche Website sensible Daten von einer anderen Website liest. Manchmal möchten Sie möglicherweise anderen Websites erlauben, ursprungsübergreifende Anforderungen an Ihre App zu senden. Weitere Informationen finden Sie im Mozilla CORS-Artikel.
Ursprungsübergreifende Ressourcenfreigabe (Cross Origin Resource Sharing , CORS):
- Ist ein W3C-Standard, der es einem Server ermöglicht, die Richtlinie für denselben Ursprung zu lockern.
- Ist kein Sicherheitsfeature, CORS lockert die Sicherheit. Eine API ist nicht sicherer, indem CORS zugelassen wird. Weitere Informationen finden Sie unter Funktionsweise von CORS.
- Ermöglicht einem Server, einige ursprungsübergreifende Anforderungen explizit zuzulassen, während andere abgelehnt werden.
- Ist sicherer und flexibler als frühere Techniken wie JSONP.
Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)
Gleicher Ursprung
Zwei URLs haben denselben Ursprung, wenn sie über identische Schemas, Hosts und Ports verfügen (RFC 6454).
Diese beiden URLs haben denselben Ursprung:
https://example.com/foo.html
https://example.com/bar.html
Diese URLs haben andere Ursprünge als die vorherigen beiden URLs:
https://example.net
: Andere Domänehttps://www.example.com/foo.html
: Andere Unterdomänehttp://example.com/foo.html
: Anderes Schemahttps://example.com:9000/foo.html
: Anderer Port
Aktivieren von CORS
Es gibt drei Möglichkeiten, CORS zu aktivieren:
- In Middleware mit einer benannten OderStandardrichtlinie.
- Verwenden von Endpunktrouting.
- Mit dem [EnableCors] -Attribut.
Die Verwendung des [EnableCors]-Attributs mit einer benannten Richtlinie bietet die beste Kontrolle bei der Begrenzung von Endpunkten, die CORS unterstützen.
Warnung
UseCors muss in der richtigen Reihenfolge aufgerufen werden. Weitere Informationen finden Sie unter Middlewarereihenfolge. Muss z. UseCors
B. vor UseResponseCaching der Verwendung UseResponseCaching
von aufgerufen werden.
Jeder Ansatz wird in den folgenden Abschnitten erläutert.
CORS mit benannter Richtlinie und Middleware
CORS-Middleware verarbeitet ursprungsübergreifende Anforderungen. Der folgende Code wendet eine CORS-Richtlinie auf alle Endpunkte der App mit den angegebenen Ursprüngen an:
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
// services.AddResponseCaching();
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors(MyAllowSpecificOrigins);
app.UseAuthorization();
app.MapControllers();
app.Run();
Der vorangehende Code:
- Legt den Richtliniennamen auf fest
_myAllowSpecificOrigins
. Der Richtlinienname ist beliebig. - Ruft die UseCors Erweiterungsmethode auf und gibt die CORS-Richtlinie
_myAllowSpecificOrigins
an.UseCors
fügt die CORS-Middleware hinzu. Der Aufruf vonUseCors
muss nachUseRouting
, aber vorUseAuthorization
platziert werden. Weitere Informationen finden Sie unter Middlewarereihenfolge. - Aufrufe AddCors mit einem Lambdaausdruck. Das Lambda nimmt ein CorsPolicyBuilder -Objekt an. Konfigurationsoptionen wie
WithOrigins
werden weiter unten in diesem Artikel beschrieben. - Aktiviert die CORS-Richtlinie
_myAllowSpecificOrigins
für alle Controllerendpunkte. Informationen zum Anwenden einer CORS-Richtlinie auf bestimmte Endpunkte finden Sie unter Endpunktrouting . - Wenn Sie die Middleware für die Antwortzwischenspeicherung verwenden, rufen Sie UseCors vor auf UseResponseCaching.
Beim Endpunktrouting muss die CORS-Middleware für die Ausführung zwischen den Aufrufen von UseRouting
und UseEndpoints
konfiguriert werden.
Anweisungen zum Testen von Code ähnlich dem vorherigen Code finden Sie unter Testen von CORS .
Der AddCors Methodenaufruf fügt CORS-Dienste zum Dienstcontainer der App hinzu:
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
// services.AddResponseCaching();
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors(MyAllowSpecificOrigins);
app.UseAuthorization();
app.MapControllers();
app.Run();
Weitere Informationen finden Sie unter CORS-Richtlinienoptionen in diesem Dokument.
Die CorsPolicyBuilder Methoden können verkettet werden, wie im folgenden Code gezeigt:
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors(MyAllowSpecificOrigins);
app.UseAuthorization();
app.MapControllers();
app.Run();
Hinweis: Die angegebene URL darf keinen nachgestellten Schrägstrich (/
) enthalten. Wenn die URL mit /
beendet wird, gibt der Vergleich zurück false
, und es wird kein Header zurückgegeben.
Reihenfolge von UseCors und UseStaticFiles
UseStaticFiles
In der Regel wird vor UseCors
aufgerufen. Apps, die JavaScript zum websiteübergreifenden Abrufen statischer Dateien verwenden, müssen vor UseStaticFiles
aufrufenUseCors
.
CORS mit Standardrichtlinie und Middleware
Der folgende hervorgehobene Code aktiviert die CORS-Standardrichtlinie:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.MapControllers();
app.Run();
Der vorangehende Code wendet die CORS-Standardrichtlinie auf alle Controllerendpunkte an.
Aktivieren von Cors mit Endpunktrouting
Die Aktivierung von CORS pro Endpunkt mit unterstützt RequireCors
keine automatischen Preflightanforderungen. Weitere Informationen finden Sie in diesem GitHub-Problem und unter Testen von CORS mit Endpunktrouting und [HttpOptions].
Beim Endpunktrouting kann CORS auf Endpunktbasis mithilfe der RequireCors Erweiterungsmethoden aktiviert werden:
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
builder.Services.AddControllers();
builder.Services.AddRazorPages();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/echo",
context => context.Response.WriteAsync("echo"))
.RequireCors(MyAllowSpecificOrigins);
endpoints.MapControllers()
.RequireCors(MyAllowSpecificOrigins);
endpoints.MapGet("/echo2",
context => context.Response.WriteAsync("echo2"));
endpoints.MapRazorPages();
});
app.Run();
Für den Code oben gilt:
app.UseCors
aktiviert die CORS-Middleware. Da keine Standardrichtlinie konfiguriert wurde,app.UseCors()
wird CORS allein nicht aktiviert.- Die
/echo
Controllerendpunkte und ermöglichen ursprungsübergreifende Anforderungen mithilfe der angegebenen Richtlinie. - Die
/echo2
Pages-Endpunkte und Razor lassen ursprungsübergreifende Anforderungen nicht zu, da keine Standardrichtlinie angegeben wurde.
Das [DisableCors] -Attribut deaktiviert cors nicht , das durch Endpunktrouting mit RequireCors
aktiviert wurde.
Anweisungen zum Testen von Code ähnlich dem vorherigen finden Sie unter Testen von CORS mit Endpunktrouting und [HttpOptions].
Aktivieren von CORS mit Attributen
Das Aktivieren von CORS mit dem [EnableCors]- Attribut und das Anwenden einer benannten Richtlinie nur auf die Endpunkte, die CORS erfordern, bietet die beste Steuerung.
Das Attribut [EnableCors] bietet eine Alternative zum globalen Anwenden von CORS. Das [EnableCors]
Attribut aktiviert CORS für ausgewählte Endpunkte und nicht für alle Endpunkte:
[EnableCors]
gibt die Standardrichtlinie an.[EnableCors("{Policy String}")]
gibt eine benannte Richtlinie an.
Das [EnableCors]
Attribut kann auf Folgendes angewendet werden:
- Razor Seite
PageModel
- Controller
- Controlleraktionsmethode
Mit dem [EnableCors]
-Attribut können verschiedene Richtlinien auf Controller, Seitenmodelle oder Aktionsmethoden angewendet werden. Wenn das [EnableCors]
Attribut auf einen Controller, ein Seitenmodell oder eine Aktionsmethode angewendet wird und CORS in middleware aktiviert ist, werden beide Richtlinien angewendet. Es wird davon abgeraten, Richtlinien zu kombinieren. Verwenden Sie die Schaltfläche [EnableCors]
Attribut oder Middleware, nicht beide in derselben App.
Der folgende Code wendet eine andere Richtlinie auf jede Methode an:
[Route("api/[controller]")]
[ApiController]
public class WidgetController : ControllerBase
{
// GET api/values
[EnableCors("AnotherPolicy")]
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { "green widget", "red widget" };
}
// GET api/values/5
[EnableCors("Policy1")]
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
return id switch
{
1 => "green widget",
2 => "red widget",
_ => NotFound(),
};
}
}
Der folgende Code erstellt zwei CORS-Richtlinien:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("Policy1",
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
options.AddPolicy("AnotherPolicy",
policy =>
{
policy.WithOrigins("http://www.contoso.com")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.MapControllers();
app.Run();
Für die beste Kontrolle der Begrenzung von CORS-Anforderungen:
- Verwenden Sie
[EnableCors("MyPolicy")]
mit einer benannten Richtlinie. - Definieren Sie keine Standardrichtlinie.
- Verwenden Sie kein Endpunktrouting.
Der Code im nächsten Abschnitt entspricht der vorherigen Liste.
Anweisungen zum Testen von Code, der dem vorherigen Code ähnelt, finden Sie unter Testen von CORS .
Deaktivieren von CORS
Das [DisableCors] -Attribut deaktiviert keine CORS, die durch Endpunktrouting aktiviert wurde.
Der folgende Code definiert die CORS-Richtlinie "MyPolicy"
:
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: "MyPolicy",
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com")
.WithMethods("PUT", "DELETE", "GET");
});
});
builder.Services.AddControllers();
builder.Services.AddRazorPages();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.MapControllers();
app.MapRazorPages();
app.Run();
Der folgende Code deaktiviert CORS für die GetValues2
Aktion:
[EnableCors("MyPolicy")]
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public IActionResult Get() =>
ControllerContext.MyDisplayRouteInfo();
// GET api/values/5
[HttpGet("{id}")]
public IActionResult Get(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// PUT api/values/5
[HttpPut("{id}")]
public IActionResult Put(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// GET: api/values/GetValues2
[DisableCors]
[HttpGet("{action}")]
public IActionResult GetValues2() =>
ControllerContext.MyDisplayRouteInfo();
}
Der vorangehende Code:
- Aktiviert CORS nicht mit Endpunktrouting.
- Definiert keine CORS-Standardrichtlinie.
- Verwendet [EnableCors("MyPolicy")], um die CORS-Richtlinie
"MyPolicy"
für den Controller zu aktivieren. - Deaktiviert CORS für die
GetValues2
-Methode.
Anweisungen zum Testen des vorherigen Codes finden Sie unter Testen von CORS .
CORS-Richtlinienoptionen
In diesem Abschnitt werden die verschiedenen Optionen beschrieben, die in einer CORS-Richtlinie festgelegt werden können:
- Festlegen der zulässigen Ursprünge
- Festlegen der zulässigen HTTP-Methoden
- Festlegen der zulässigen Anforderungsheader
- Festlegen der verfügbar gemachten Antwortheader
- Anmeldeinformationen in ursprungsübergreifenden Anforderungen
- Festlegen der Preflight-Ablaufzeit
AddPolicy wird in Program.cs
aufgerufen. Für einige Optionen kann es hilfreich sein, zuerst den Abschnitt Funktionsweise von CORS zu lesen.
Festlegen der zulässigen Ursprünge
AllowAnyOrigin: Ermöglicht CORS-Anforderungen aus allen Ursprüngen mit einem beliebigen Schema (http
oder https
). AllowAnyOrigin
ist unsicher, da jede Website ursprungsübergreifende Anforderungen an die App stellen kann.
Hinweis
Die Angabe von AllowAnyOrigin
und AllowCredentials
ist eine unsichere Konfiguration und kann zu standortübergreifender Anforderungsfälschung führen. Der CORS-Dienst gibt eine ungültige CORS-Antwort zurück, wenn eine App mit beiden Methoden konfiguriert ist.
AllowAnyOrigin
wirkt sich auf Preflight-Anforderungen und den Access-Control-Allow-Origin
Header aus. Weitere Informationen finden Sie im Abschnitt Preflight-Anforderungen .
SetIsOriginAllowedToAllowWildcardSubdomains: Legt die IsOriginAllowed -Eigenschaft der Richtlinie als Funktion fest, die es Ursprüngen ermöglicht, einer konfigurierten Feldhalterdomäne bei der Bewertung zu entsprechen, ob der Ursprung zulässig ist.
var MyAllowSpecificOrigins = "_MyAllowSubdomainPolicy";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("https://*.example.com")
.SetIsOriginAllowedToAllowWildcardSubdomains();
});
});
builder.Services.AddControllers();
var app = builder.Build();
Festlegen der zulässigen HTTP-Methoden
- Ermöglicht jede HTTP-Methode:
- Wirkt sich auf Preflight-Anforderungen und den
Access-Control-Allow-Methods
Header aus. Weitere Informationen finden Sie im Abschnitt Preflight-Anforderungen .
Festlegen der zulässigen Anforderungsheader
Rufen WithHeaders Sie die zulässigen Header auf, um das Senden bestimmter Header in einer CORS-Anforderung als Autorenanforderungsheader zuzulassen:
using Microsoft.Net.Http.Headers;
var MyAllowSpecificOrigins = "_MyAllowSubdomainPolicy";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com")
.WithHeaders(HeaderNames.ContentType, "x-custom-header");
});
});
builder.Services.AddControllers();
var app = builder.Build();
Rufen Sie zum Zulassen aller Autorenanforderungsheader auf AllowAnyHeader:
var MyAllowSpecificOrigins = "_MyAllowSubdomainPolicy";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("https://*.example.com")
.AllowAnyHeader();
});
});
builder.Services.AddControllers();
var app = builder.Build();
AllowAnyHeader
wirkt sich auf Preflight-Anforderungen und den Access-Control-Request-Headers-Headers aus. Weitere Informationen finden Sie im Abschnitt Preflight-Anforderungen .
Eine Übereinstimmung der CORS-Middleware-Richtlinie mit bestimmten Headern, die durch WithHeaders
angegeben werden, ist nur möglich, wenn die gesendeten Access-Control-Request-Headers
Header genau mit den in WithHeaders
angegebenen Headern übereinstimmen.
Betrachten Sie beispielsweise eine App, die wie folgt konfiguriert ist:
app.UseCors(policy => policy.WithHeaders(HeaderNames.CacheControl));
CORS Middleware lehnt eine Preflight-Anforderung mit dem folgenden Anforderungsheader ab, da Content-Language
(HeaderNames.ContentLanguage) nicht in WithHeaders
aufgeführt ist:
Access-Control-Request-Headers: Cache-Control, Content-Language
Die App gibt eine Antwort mit 200 OK zurück, sendet die CORS-Header jedoch nicht zurück. Daher versucht der Browser die ursprungsübergreifende Anforderung nicht.
Festlegen der verfügbar gemachten Antwortheader
Standardmäßig macht der Browser nicht alle Antwortheader für die App verfügbar. Weitere Informationen finden Sie unter W3C Cross-Origin Resource Sharing (Terminologie): Einfacher Antwortheader.
Standardmäßig sind folgende Antwortheader verfügbar:
Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma
Die CORS-Spezifikation ruft diese Header als einfache Antwortheader auf. Rufen Sie folgendes auf WithExposedHeaders, um andere Header für die App verfügbar zu machen:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MyExposeResponseHeadersPolicy",
policy =>
{
policy.WithOrigins("https://*.example.com")
.WithExposedHeaders("x-custom-header");
});
});
builder.Services.AddControllers();
var app = builder.Build();
Anmeldeinformationen in ursprungsübergreifenden Anforderungen
Anmeldeinformationen erfordern eine spezielle Behandlung in einer CORS-Anforderung. Standardmäßig sendet der Browser keine Anmeldeinformationen mit einer ursprungsübergreifenden Anforderung. Anmeldeinformationen umfassen cookies- und HTTP-Authentifizierungsschemas. Um Anmeldeinformationen mit einer ursprungsübergreifenden Anforderung zu senden, muss der Client auf true
festlegenXMLHttpRequest.withCredentials
.
Direkte Verwendung XMLHttpRequest
:
var xhr = new XMLHttpRequest();
xhr.open('get', 'https://www.example.com/api/test');
xhr.withCredentials = true;
Verwenden von jQuery:
$.ajax({
type: 'get',
url: 'https://www.example.com/api/test',
xhrFields: {
withCredentials: true
}
});
Verwenden der Abruf-API:
fetch('https://www.example.com/api/test', {
credentials: 'include'
});
Der Server muss die Anmeldeinformationen zulassen. Um ursprungsübergreifende Anmeldeinformationen zuzulassen, rufen Sie folgendes auf AllowCredentials:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MyMyAllowCredentialsPolicy",
policy =>
{
policy.WithOrigins("http://example.com")
.AllowCredentials();
});
});
builder.Services.AddControllers();
var app = builder.Build();
Die HTTP-Antwort enthält einen Access-Control-Allow-Credentials
Header, der dem Browser mitteilt, dass der Server Anmeldeinformationen für eine ursprungsübergreifende Anforderung zulässt.
Wenn der Browser Anmeldeinformationen sendet, die Antwort aber keinen gültigen Access-Control-Allow-Credentials
Header enthält, macht der Browser die Antwort für die App nicht verfügbar, und die ursprungsübergreifende Anforderung schlägt fehl.
Das Zulassen von ursprungsübergreifenden Anmeldeinformationen ist ein Sicherheitsrisiko. Eine Website in einer anderen Domäne kann die Anmeldeinformationen eines angemeldeten Benutzers im Namen des Benutzers ohne Wissen des Benutzers an die App senden.
Die CORS-Spezifikation besagt auch, dass das Festlegen von Ursprüngen auf "*"
(alle Ursprünge) ungültig ist, wenn der Access-Control-Allow-Credentials
Header vorhanden ist.
Preflight-Anforderungen
Bei einigen CORS-Anforderungen sendet der Browser vor der eigentlichen Anforderung eine zusätzliche OPTIONS-Anforderung . Diese Anforderung wird als Preflight-Anforderung bezeichnet. Der Browser kann die Preflight-Anforderung überspringen, wenn alle folgenden Bedingungen erfüllt sind:
- Die Anforderungsmethode ist GET, HEAD oder POST.
- Die App legt keine anderen Anforderungsheader als
Accept
, ,Accept-Language
Content-Language
,Content-Type
oderLast-Event-ID
fest. - Falls festgelegt, weist der
Content-Type
Header einen der folgenden Werte auf:application/x-www-form-urlencoded
multipart/form-data
text/plain
Die Für die Clientanforderung festgelegte Regel für Anforderungsheader gilt für Header, die die App durch Aufrufen setRequestHeader
des XMLHttpRequest
-Objekts festlegt. Die CORS-Spezifikation ruft diese Header für Autorenanforderungsheader auf. Die Regel gilt nicht für Header, die der Browser festlegen kann, z User-Agent
. B. , Host
oder Content-Length
.
Die folgende Beispielantwort ähnelt der Preflight-Anforderung über die Schaltfläche [Test ablegen] im Abschnitt CORS testen dieses Dokuments.
General:
Request URL: https://cors3.azurewebsites.net/api/values/5
Request Method: OPTIONS
Status Code: 204 No Content
Response Headers:
Access-Control-Allow-Methods: PUT,DELETE,GET
Access-Control-Allow-Origin: https://cors1.azurewebsites.net
Server: Microsoft-IIS/10.0
Set-Cookie: ARRAffinity=8f8...8;Path=/;HttpOnly;Domain=cors1.azurewebsites.net
Vary: Origin
Request Headers:
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Access-Control-Request-Method: PUT
Connection: keep-alive
Host: cors3.azurewebsites.net
Origin: https://cors1.azurewebsites.net
Referer: https://cors1.azurewebsites.net/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0
Die Preflight-Anforderung verwendet die HTTP OPTIONS-Methode . Es kann die folgenden Header enthalten:
- Access-Control-Request-Method: Die HTTP-Methode, die für die tatsächliche Anforderung verwendet wird.
- Access-Control-Request-Headers: Eine Liste der Anforderungsheader, die die App für die tatsächliche Anforderung festlegt. Wie bereits erwähnt, enthält dies keine Header, die vom Browser festgelegt werden, z. B
User-Agent
. . - Access-Control-Allow-Methods
Wenn die Preflight-Anforderung abgelehnt wird, gibt die App eine 200 OK
Antwort zurück, legt aber die CORS-Header nicht fest. Daher versucht der Browser die ursprungsübergreifende Anforderung nicht. Ein Beispiel für eine verweigerte Preflight-Anforderung finden Sie im Abschnitt CORS-Test dieses Dokuments.
Bei Verwendung der F12-Tools zeigt die Konsolen-App je nach Browser einen Fehler ähnlich einem der folgenden an:
- Firefox: Cross-Origin Request Blockiert: Die gleiche Ursprungsrichtlinie lässt das Lesen der Remoteressource unter nicht zu
https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5
. (Grund: CORS-Anforderung war nicht erfolgreich). Weitere Informationen - Chromium basiert: Der Zugriff auf den Abruf von "https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5" vom Ursprung "https://cors3.azurewebsites.net" wurde durch die CORS-Richtlinie blockiert: Die Antwort auf eine Preflight-Anforderung besteht nicht über die Zugriffssteuerungsprüfung: Für die angeforderte Ressource ist kein "Access-Control-Allow-Origin"-Header vorhanden. Falls eine opake Antwort Ihre Anforderungen erfüllt, legen Sie den Modus der Anforderung auf 'no-cors' fest, um CORS für den Ressourcenabruf zu deaktivieren.
Um bestimmte Header zuzulassen, rufen Sie folgendes auf WithHeaders:
using Microsoft.Net.Http.Headers;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MyAllowHeadersPolicy",
policy =>
{
policy.WithOrigins("http://example.com")
.WithHeaders(HeaderNames.ContentType, "x-custom-header");
});
});
builder.Services.AddControllers();
var app = builder.Build();
Rufen Sie zum Zulassen aller Autorenanforderungsheader auf AllowAnyHeader:
using Microsoft.Net.Http.Headers;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MyAllowAllHeadersPolicy",
policy =>
{
policy.WithOrigins("https://*.example.com")
.AllowAnyHeader();
});
});
builder.Services.AddControllers();
var app = builder.Build();
Browser sind nicht konsistent, wenn sie festlegen Access-Control-Request-Headers
. Wenn einer der folgenden Aktionen zu beachten ist:
- Header sind auf alles andere als festgelegt.
"*"
- AllowAnyHeader wird aufgerufen: Schließen Sie mindestens
Accept
,Content-Type
undOrigin
sowie alle benutzerdefinierten Header ein, die Sie unterstützen möchten.
Code für automatische Preflight-Anforderung
Wenn die CORS-Richtlinie angewendet wird:
- Global durch Aufrufen
app.UseCors
von inProgram.cs
. - Verwenden des -Attributs
[EnableCors]
.
ASP.NET Core antwortet auf die OPTIONS-Anforderung im Preflight.
Die Aktivierung von CORS pro Endpunkt mit unterstützt RequireCors
derzeit keine automatischen Preflightanforderungen.
Im Abschnitt CORS testen dieses Dokuments wird dieses Verhalten veranschaulicht.
[HttpOptions]-Attribut für Preflight-Anforderungen
Wenn CORS mit der entsprechenden Richtlinie aktiviert ist, antwortet ASP.NET Core in der Regel automatisch auf CORS-Preflight-Anforderungen. In einigen Szenarien ist dies möglicherweise nicht der Fall. Beispiel: Verwenden von CORS mit Endpunktrouting.
Der folgende Code verwendet das [HttpOptions]- Attribut, um Endpunkte für OPTIONS-Anforderungen zu erstellen:
[Route("api/[controller]")]
[ApiController]
public class TodoItems2Controller : ControllerBase
{
// OPTIONS: api/TodoItems2/5
[HttpOptions("{id}")]
public IActionResult PreflightRoute(int id)
{
return NoContent();
}
// OPTIONS: api/TodoItems2
[HttpOptions]
public IActionResult PreflightRoute()
{
return NoContent();
}
[HttpPut("{id}")]
public IActionResult PutTodoItem(int id)
{
if (id < 1)
{
return BadRequest();
}
return ControllerContext.MyDisplayRouteInfo(id);
}
Anweisungen zum Testen des vorherigen Codes finden Sie unter Testen von CORS mit Endpunktrouting und [HttpOptions].
Festlegen der Preflight-Ablaufzeit
Der Access-Control-Max-Age
Header gibt an, wie lange die Antwort auf die Preflightanforderung zwischengespeichert werden kann. Um diesen Header festzulegen, rufen Sie auf SetPreflightMaxAge:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MySetPreflightExpirationPolicy",
policy =>
{
policy.WithOrigins("http://example.com")
.SetPreflightMaxAge(TimeSpan.FromSeconds(2520));
});
});
builder.Services.AddControllers();
var app = builder.Build();
Funktionsweise von CORS
In diesem Abschnitt wird beschrieben, was in einer CORS-Anforderung auf der Ebene der HTTP-Nachrichten geschieht.
- CORS ist kein Sicherheitsfeature. CORS ist ein W3C-Standard, mit dem ein Server die Richtlinie für denselben Ursprung lockern kann.
- Beispielsweise könnte ein böswilliger Akteur Cross-Site Scripting (XSS) für Ihre Website verwenden und eine websiteübergreifende Anforderung an seine CORS-fähige Website ausführen, um Informationen zu stehlen.
- Eine API ist nicht sicherer, indem CORS zugelassen wird.
- Es liegt am Client (Browser), CORS zu erzwingen. Der Server führt die Anforderung aus und gibt die Antwort zurück. Es ist der Client, der einen Fehler zurückgibt und die Antwort blockiert. Beispielsweise zeigt eines der folgenden Tools die Serverantwort an:
- Fiddler
- Postman
- .NET HttpClient
- Einen Webbrowser, indem Sie die URL in die Adressleiste eingeben.
- Es liegt am Client (Browser), CORS zu erzwingen. Der Server führt die Anforderung aus und gibt die Antwort zurück. Es ist der Client, der einen Fehler zurückgibt und die Antwort blockiert. Beispielsweise zeigt eines der folgenden Tools die Serverantwort an:
- Es ist eine Möglichkeit für einen Server, Browsern die Ausführung einer ursprungsübergreifenden XHR - oder Fetch-API-Anforderung zu ermöglichen, die andernfalls verboten wäre.
- Browser ohne CORS können keine ursprungsübergreifenden Anforderungen ausführen. Vor CORS wurde ONP verwendet,JS um diese Einschränkung zu umgehen. JSONP verwendet nicht XHR, es verwendet das
<script>
-Tag, um die Antwort zu empfangen. Skripts dürfen ursprungsübergreifend geladen werden.
- Browser ohne CORS können keine ursprungsübergreifenden Anforderungen ausführen. Vor CORS wurde ONP verwendet,JS um diese Einschränkung zu umgehen. JSONP verwendet nicht XHR, es verwendet das
Mit der CORS-Spezifikation wurden mehrere neue HTTP-Header eingeführt, die ursprungsübergreifende Anforderungen ermöglichen. Wenn ein Browser CORS unterstützt, werden diese Header automatisch für ursprungsübergreifende Anforderungen festgelegt. Benutzerdefinierter JavaScript-Code ist nicht erforderlich, um CORS zu aktivieren.
Schaltfläche "PUT-Test" im bereitgestellten Beispiel
Im Folgenden finden Sie ein Beispiel für eine ursprungsübergreifende Anforderung über die Schaltfläche Wertetest an https://cors1.azurewebsites.net/api/values
. Der Origin
Header:
- Stellt die Domäne des Standorts bereit, der die Anforderung stellt.
- Ist erforderlich und muss sich vom Host unterscheiden.
Allgemeine Header
Request URL: https://cors1.azurewebsites.net/api/values
Request Method: GET
Status Code: 200 OK
Antwortheader
Content-Encoding: gzip
Content-Type: text/plain; charset=utf-8
Server: Microsoft-IIS/10.0
Set-Cookie: ARRAffinity=8f...;Path=/;HttpOnly;Domain=cors1.azurewebsites.net
Transfer-Encoding: chunked
Vary: Accept-Encoding
X-Powered-By: ASP.NET
Anforderungsheader
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Host: cors1.azurewebsites.net
Origin: https://cors3.azurewebsites.net
Referer: https://cors3.azurewebsites.net/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0 ...
In OPTIONS
Anforderungen legt der Server den Header AntwortheaderAccess-Control-Allow-Origin: {allowed origin}
in der Antwort fest. Beispielsweise enthält das bereitgestellte Beispieldelete [EnableCors] button OPTIONS
request die folgenden Header:
Allgemeine Header
Request URL: https://cors3.azurewebsites.net/api/TodoItems2/MyDelete2/5
Request Method: OPTIONS
Status Code: 204 No Content
Antwortheader
Access-Control-Allow-Headers: Content-Type,x-custom-header
Access-Control-Allow-Methods: PUT,DELETE,GET,OPTIONS
Access-Control-Allow-Origin: https://cors1.azurewebsites.net
Server: Microsoft-IIS/10.0
Set-Cookie: ARRAffinity=8f...;Path=/;HttpOnly;Domain=cors3.azurewebsites.net
Vary: Origin
X-Powered-By: ASP.NET
Anforderungsheader
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: DELETE
Connection: keep-alive
Host: cors3.azurewebsites.net
Origin: https://cors1.azurewebsites.net
Referer: https://cors1.azurewebsites.net/test?number=2
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0
In den obigen Antwortheadern legt der Server den Access-Control-Allow-Origin-Header in der Antwort fest. Der https://cors1.azurewebsites.net
Wert dieses Headers entspricht dem Origin
Header aus der Anforderung.
Wenn AllowAnyOrigin aufgerufen wird, wird zurückgegeben Access-Control-Allow-Origin: *
, der -Wildcard-Wert. AllowAnyOrigin
lässt jeden Ursprung zu.
Wenn die Antwort den Access-Control-Allow-Origin
Header nicht enthält, schlägt die ursprungsübergreifende Anforderung fehl. Insbesondere lässt der Browser die Anforderung nicht zu. Selbst wenn der Server eine erfolgreiche Antwort zurückgibt, stellt der Browser die Antwort nicht für die Client-App zur Verfügung.
Http-Umleitung zu HTTPS verursacht ERR_INVALID_REDIRECT für die CORS-Preflightanforderung
Anforderungen an einen Endpunkt mithilfe von UseHttpsRedirection HTTP, die an HTTPS umgeleitet werden, schlagen mit ERR_INVALID_REDIRECT on the CORS preflight request
fehl.
API-Projekte können HTTP-Anforderungen ablehnen, anstatt UseHttpsRedirection
Anforderungen an HTTPS umzuleiten.
Anzeigen von OPTIONS-Anforderungen
Standardmäßig zeigen die Browser Chrome und Edge keine OPTIONS-Anforderungen auf der Registerkarte "Netzwerk" der F12-Tools an. So zeigen Sie OPTIONS-Anforderungen in diesen Browsern an:
chrome://flags/#out-of-blink-cors
oderedge://flags/#out-of-blink-cors
- deaktivieren Sie das Flag.
- „Neu starten“.
Firefox zeigt standardmäßig OPTIONS-Anforderungen an.
CORS in IIS
Bei der Bereitstellung in IIS muss CORS vor der Windows-Authentifizierung ausgeführt werden, wenn der Server nicht für anonymen Zugriff konfiguriert ist. Um dieses Szenario zu unterstützen, muss das IIS CORS-Modul für die App installiert und konfiguriert werden.
Testen von CORS
Der Beispieldownload enthält Code zum Testen von CORS. Informationen zum Herunterladen finden Sie hier. Das Beispiel ist ein API-Projekt mit hinzugefügten Razor Seiten:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: "MyPolicy",
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com",
"https://cors1.azurewebsites.net",
"https://cors3.azurewebsites.net",
"https://localhost:44398",
"https://localhost:5001")
.WithMethods("PUT", "DELETE", "GET");
});
});
builder.Services.AddControllers();
builder.Services.AddRazorPages();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.MapControllers();
app.MapRazorPages();
app.Run();
Warnung
WithOrigins("https://localhost:<port>");
sollte nur zum Testen einer Beispiel-App verwendet werden, die dem Downloadbeispielcode ähnelt.
Im Folgenden ValuesController
werden die Endpunkte für Tests bereitgestellt:
[EnableCors("MyPolicy")]
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public IActionResult Get() =>
ControllerContext.MyDisplayRouteInfo();
// GET api/values/5
[HttpGet("{id}")]
public IActionResult Get(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// PUT api/values/5
[HttpPut("{id}")]
public IActionResult Put(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// GET: api/values/GetValues2
[DisableCors]
[HttpGet("{action}")]
public IActionResult GetValues2() =>
ControllerContext.MyDisplayRouteInfo();
}
MyDisplayRouteInfo wird von dem NuGet-Paket Rick.Docs.Samples.RouteInfo bereitgestellt und zeigt Routeninformationen an.
Testen Sie den obigen Beispielcode mit einem der folgenden Ansätze:
- Verwenden Sie die bereitgestellte Beispiel-App unter https://cors3.azurewebsites.net/. Es ist nicht erforderlich, das Beispiel herunterzuladen.
- Führen Sie das Beispiel mit
dotnet run
der Standard-URL aushttps://localhost:5001
. - Führen Sie das Beispiel in Visual Studio aus, wobei der Port für die URL auf 44398 festgelegt ist
https://localhost:44398
.
Verwenden eines Browsers mit den F12-Tools:
Wählen Sie die Schaltfläche Werte aus, und überprüfen Sie die Kopfzeilen auf der Registerkarte Netzwerk .
Wählen Sie die Schaltfläche PUT-Test aus. Anweisungen zum Anzeigen der OPTIONS-Anforderung finden Sie unter Anzeigen von OPTIONS-Anforderungen . Der PUT-Test erstellt zwei Anforderungen: eine OPTIONS-Preflightanforderung und die PUT-Anforderung.
Wählen Sie die
GetValues2 [DisableCors]
Schaltfläche aus, um eine fehlerhafte CORS-Anforderung auszulösen. Wie im Dokument erwähnt, gibt die Antwort 200 success zurück, aber die CORS-Anforderung wird nicht gestellt. Wählen Sie die Registerkarte Konsole aus, um den CORS-Fehler anzuzeigen. Je nach Browser wird ein Fehler ähnlich dem folgenden angezeigt:Der Zugriff zum Abrufen vom
'https://cors1.azurewebsites.net/api/values/GetValues2'
Ursprung'https://cors3.azurewebsites.net'
wurde durch die CORS-Richtlinie blockiert: Für die angeforderte Ressource ist kein "Access-Control-Allow-Origin"-Header vorhanden. Falls eine opake Antwort Ihre Anforderungen erfüllt, legen Sie den Modus der Anforderung auf 'no-cors' fest, um CORS für den Ressourcenabruf zu deaktivieren.
CORS-fähige Endpunkte können mit einem Tool wie curl, Fiddler oder Postman getestet werden. Wenn Sie ein Tool verwenden, muss sich der Vom -Header angegebene Ursprung der Origin
Anforderung von dem Host unterscheiden, der die Anforderung empfängt. Wenn die Anforderung nicht den kreuzigen Ursprung basierend auf dem Wert des Headers Origin
aufweist:
- Es ist nicht erforderlich, dass CORS-Middleware die Anforderung verarbeitet.
- CORS-Header werden in der Antwort nicht zurückgegeben.
Der folgende Befehl verwendet curl
, um eine OPTIONS-Anforderung mit Informationen ausstellen:
curl -X OPTIONS https://cors3.azurewebsites.net/api/TodoItems2/5 -i
Testen von CORS mit Endpunktrouting und [HttpOptions]
Die Aktivierung von CORS pro Endpunkt mit unterstützt RequireCors
derzeit keineautomatischen Preflightanforderungen. Betrachten Sie den folgenden Code, der Endpunktrouting verwendet, um CORS zu aktivieren:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: "MyPolicy",
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com",
"https://cors1.azurewebsites.net",
"https://cors3.azurewebsites.net",
"https://localhost:44398",
"https://localhost:5001")
.WithMethods("PUT", "DELETE", "GET");
});
});
builder.Services.AddControllers();
builder.Services.AddRazorPages();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.MapControllers();
app.MapRazorPages();
app.Run();
Im Folgenden TodoItems1Controller
werden Endpunkte für Tests bereitgestellt:
[Route("api/[controller]")]
[ApiController]
public class TodoItems1Controller : ControllerBase
{
// PUT: api/TodoItems1/5
[HttpPut("{id}")]
public IActionResult PutTodoItem(int id)
{
if (id < 1)
{
return Content($"ID = {id}");
}
return ControllerContext.MyDisplayRouteInfo(id);
}
// Delete: api/TodoItems1/5
[HttpDelete("{id}")]
public IActionResult MyDelete(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// GET: api/TodoItems1
[HttpGet]
public IActionResult GetTodoItems() =>
ControllerContext.MyDisplayRouteInfo();
[EnableCors]
[HttpGet("{action}")]
public IActionResult GetTodoItems2() =>
ControllerContext.MyDisplayRouteInfo();
// Delete: api/TodoItems1/MyDelete2/5
[EnableCors]
[HttpDelete("{action}/{id}")]
public IActionResult MyDelete2(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
}
Testen Sie den vorherigen Code auf der Testseite des bereitgestellten Beispiels.
Die Schaltflächen Löschen [EnableCors] und GET [EnableCors] sind erfolgreich, da die Endpunkte Preflight-Anforderungen enthalten [EnableCors]
und darauf reagieren. Bei den anderen Endpunkten tritt ein Fehler auf. Die Get-Schaltfläche schlägt fehl, da JavaScript Folgendes sendet:
headers: {
"Content-Type": "x-custom-header"
},
Im Folgenden TodoItems2Controller
werden ähnliche Endpunkte bereitgestellt, aber expliziter Code zum Reagieren auf OPTIONS-Anforderungen:
[Route("api/[controller]")]
[ApiController]
public class TodoItems2Controller : ControllerBase
{
// OPTIONS: api/TodoItems2/5
[HttpOptions("{id}")]
public IActionResult PreflightRoute(int id)
{
return NoContent();
}
// OPTIONS: api/TodoItems2
[HttpOptions]
public IActionResult PreflightRoute()
{
return NoContent();
}
[HttpPut("{id}")]
public IActionResult PutTodoItem(int id)
{
if (id < 1)
{
return BadRequest();
}
return ControllerContext.MyDisplayRouteInfo(id);
}
// [EnableCors] // Not needed as OPTIONS path provided
[HttpDelete("{id}")]
public IActionResult MyDelete(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
[EnableCors] // Rquired for this path
[HttpGet]
public IActionResult GetTodoItems() =>
ControllerContext.MyDisplayRouteInfo();
[HttpGet("{action}")]
public IActionResult GetTodoItems2() =>
ControllerContext.MyDisplayRouteInfo();
[EnableCors] // Rquired for this path
[HttpDelete("{action}/{id}")]
public IActionResult MyDelete2(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
}
Testen Sie den vorherigen Code auf der Testseite des bereitgestellten Beispiels. Wählen Sie in der Dropdownliste Controllerdie Option Preflight und dann Controller festlegen aus. Alle CORS-Aufrufe der TodoItems2Controller
Endpunkte sind erfolgreich.
Zusätzliche Ressourcen
Von Rick Anderson und Kirk Larkin
In diesem Artikel erfahren Sie, wie Sie CORS in einer ASP.NET Core-App aktivieren.
Die Browsersicherheit verhindert, dass eine Webseite Anforderungen an eine andere Domäne als diejenige stellt, die die Webseite versorgt hat. Diese Einschränkung wird als Richtlinie des gleichen Ursprungs bezeichnet. Die Richtlinie des gleichen Ursprungs verhindert, dass eine schädliche Website sensible Daten von einer anderen Website liest. Manchmal möchten Sie möglicherweise anderen Websites erlauben, ursprungsübergreifende Anforderungen an Ihre App zu senden. Weitere Informationen finden Sie im Mozilla CORS-Artikel.
Ursprungsübergreifende Ressourcenfreigabe (Cross Origin Resource Sharing , CORS):
- Ist ein W3C-Standard, der es einem Server ermöglicht, die Richtlinie für denselben Ursprung zu lockern.
- Ist kein Sicherheitsfeature, CORS lockert die Sicherheit. Eine API ist nicht sicherer, indem CORS zugelassen wird. Weitere Informationen finden Sie unter Funktionsweise von CORS.
- Ermöglicht einem Server, einige ursprungsübergreifende Anforderungen explizit zuzulassen, während andere abgelehnt werden.
- Ist sicherer und flexibler als frühere Techniken wie JSONP.
Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)
Gleicher Ursprung
Zwei URLs haben denselben Ursprung, wenn sie über identische Schemas, Hosts und Ports verfügen (RFC 6454).
Diese beiden URLs haben denselben Ursprung:
https://example.com/foo.html
https://example.com/bar.html
Diese URLs haben andere Ursprünge als die vorherigen beiden URLs:
https://example.net
: Andere Domänehttps://www.example.com/foo.html
: Andere Unterdomänehttp://example.com/foo.html
: Anderes Schemahttps://example.com:9000/foo.html
: Anderer Port
Aktivieren von CORS
Es gibt drei Möglichkeiten, CORS zu aktivieren:
- In Middleware mit einer benannten OderStandardrichtlinie.
- Verwenden von Endpunktrouting.
- Mit dem [EnableCors] -Attribut.
Die Verwendung des [EnableCors]-Attributs mit einer benannten Richtlinie bietet die beste Kontrolle bei der Begrenzung von Endpunkten, die CORS unterstützen.
Warnung
UseCors muss in der richtigen Reihenfolge aufgerufen werden. Weitere Informationen finden Sie unter Middlewarereihenfolge. Muss z. UseCors
B. vor UseResponseCaching der Verwendung UseResponseCaching
von aufgerufen werden.
Jeder Ansatz wird in den folgenden Abschnitten erläutert.
CORS mit benannter Richtlinie und Middleware
CORS-Middleware verarbeitet ursprungsübergreifende Anforderungen. Der folgende Code wendet eine CORS-Richtlinie auf alle Endpunkte der App mit den angegebenen Ursprüngen an:
public class Startup
{
readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
// services.AddResponseCaching();
services.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors(MyAllowSpecificOrigins);
// app.UseResponseCaching();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
Der vorangehende Code:
- Legt den Richtliniennamen auf fest
_myAllowSpecificOrigins
. Der Richtlinienname ist beliebig. - Ruft die UseCors Erweiterungsmethode auf und gibt die CORS-Richtlinie
_myAllowSpecificOrigins
an.UseCors
fügt die CORS-Middleware hinzu. Der Aufruf vonUseCors
muss nachUseRouting
, aber vorUseAuthorization
platziert werden. Weitere Informationen finden Sie unter Middlewarereihenfolge. - Aufrufe AddCors mit einem Lambdaausdruck. Das Lambda nimmt ein CorsPolicyBuilder -Objekt an. Konfigurationsoptionen wie
WithOrigins
werden weiter unten in diesem Artikel beschrieben. - Aktiviert die CORS-Richtlinie
_myAllowSpecificOrigins
für alle Controllerendpunkte. Informationen zum Anwenden einer CORS-Richtlinie auf bestimmte Endpunkte finden Sie unter Endpunktrouting . - Wenn Sie die Middleware für die Antwortzwischenspeicherung verwenden, rufen Sie UseCors vor auf UseResponseCaching.
Beim Endpunktrouting muss die CORS-Middleware für die Ausführung zwischen den Aufrufen von UseRouting
und UseEndpoints
konfiguriert werden.
Anweisungen zum Testen von Code ähnlich dem vorherigen Code finden Sie unter Testen von CORS .
Der AddCors Methodenaufruf fügt CORS-Dienste zum Dienstcontainer der App hinzu:
public class Startup
{
readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
// services.AddResponseCaching();
services.AddControllers();
}
Weitere Informationen finden Sie unter CORS-Richtlinienoptionen in diesem Dokument.
Die CorsPolicyBuilder Methoden können verkettet werden, wie im folgenden Code gezeigt:
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy(MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
services.AddControllers();
}
Hinweis: Die angegebene URL darf keinen nachgestellten Schrägstrich (/
) enthalten. Wenn die URL mit /
beendet wird, gibt der Vergleich zurück false
, und es wird kein Header zurückgegeben.
CORS mit Standardrichtlinie und Middleware
Der folgende hervorgehobene Code aktiviert die CORS-Standardrichtlinie:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddDefaultPolicy(
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
services.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
Der vorangehende Code wendet die CORS-Standardrichtlinie auf alle Controllerendpunkte an.
Aktivieren von Cors mit Endpunktrouting
Die Aktivierung von CORS pro Endpunkt mit unterstützt RequireCors
keine automatischen Preflightanforderungen. Weitere Informationen finden Sie in diesem GitHub-Problem und unter Testen von CORS mit Endpunktrouting und [HttpOptions].
Beim Endpunktrouting kann CORS auf Endpunktbasis mithilfe der RequireCors Erweiterungsmethoden aktiviert werden:
public class Startup
{
readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
services.AddControllers();
services.AddRazorPages();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/echo",
context => context.Response.WriteAsync("echo"))
.RequireCors(MyAllowSpecificOrigins);
endpoints.MapControllers()
.RequireCors(MyAllowSpecificOrigins);
endpoints.MapGet("/echo2",
context => context.Response.WriteAsync("echo2"));
endpoints.MapRazorPages();
});
}
}
Für den Code oben gilt:
app.UseCors
aktiviert die CORS-Middleware. Da keine Standardrichtlinie konfiguriert wurde,app.UseCors()
wird CORS allein nicht aktiviert.- Die
/echo
Controllerendpunkte und ermöglichen ursprungsübergreifende Anforderungen mithilfe der angegebenen Richtlinie. - Die
/echo2
Pages-Endpunkte und Razor lassen ursprungsübergreifende Anforderungen nicht zu, da keine Standardrichtlinie angegeben wurde.
Das [DisableCors] -Attribut deaktiviert cors nicht , das durch Endpunktrouting mit RequireCors
aktiviert wurde.
Anweisungen zum Testen von Code ähnlich dem vorherigen finden Sie unter Testen von CORS mit Endpunktrouting und [HttpOptions].
Aktivieren von CORS mit Attributen
Das Aktivieren von CORS mit dem [EnableCors]- Attribut und das Anwenden einer benannten Richtlinie nur auf die Endpunkte, die CORS erfordern, bietet die beste Steuerung.
Das Attribut [EnableCors] bietet eine Alternative zum globalen Anwenden von CORS. Das [EnableCors]
Attribut aktiviert CORS für ausgewählte Endpunkte und nicht für alle Endpunkte:
[EnableCors]
gibt die Standardrichtlinie an.[EnableCors("{Policy String}")]
gibt eine benannte Richtlinie an.
Das [EnableCors]
Attribut kann auf Folgendes angewendet werden:
- Razor Seite
PageModel
- Controller
- Controlleraktionsmethode
Mit dem [EnableCors]
-Attribut können verschiedene Richtlinien auf Controller, Seitenmodelle oder Aktionsmethoden angewendet werden. Wenn das [EnableCors]
Attribut auf einen Controller, ein Seitenmodell oder eine Aktionsmethode angewendet wird und CORS in middleware aktiviert ist, werden beide Richtlinien angewendet. Es wird davon abgeraten, Richtlinien zu kombinieren. Verwenden Sie die Schaltfläche [EnableCors]
Attribut oder Middleware, nicht beide in derselben App.
Der folgende Code wendet eine andere Richtlinie auf jede Methode an:
[Route("api/[controller]")]
[ApiController]
public class WidgetController : ControllerBase
{
// GET api/values
[EnableCors("AnotherPolicy")]
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { "green widget", "red widget" };
}
// GET api/values/5
[EnableCors("Policy1")]
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
return id switch
{
1 => "green widget",
2 => "red widget",
_ => NotFound(),
};
}
}
Der folgende Code erstellt zwei CORS-Richtlinien:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("Policy1",
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
options.AddPolicy("AnotherPolicy",
policy =>
{
policy.WithOrigins("http://www.contoso.com")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
services.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
Für die beste Kontrolle der Begrenzung von CORS-Anforderungen:
- Verwenden Sie
[EnableCors("MyPolicy")]
mit einer benannten Richtlinie. - Definieren Sie keine Standardrichtlinie.
- Verwenden Sie kein Endpunktrouting.
Der Code im nächsten Abschnitt entspricht der vorherigen Liste.
Anweisungen zum Testen von Code ähnlich dem vorherigen Code finden Sie unter Testen von CORS .
Deaktivieren von CORS
Das [DisableCors] -Attribut deaktiviert cors nicht , das durch Endpunktrouting aktiviert wurde.
Der folgende Code definiert die CORS-Richtlinie "MyPolicy"
:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy(name: "MyPolicy",
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com")
.WithMethods("PUT", "DELETE", "GET");
});
});
services.AddControllers();
services.AddRazorPages();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapRazorPages();
});
}
}
Der folgende Code deaktiviert CORS für die GetValues2
Aktion:
[EnableCors("MyPolicy")]
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public IActionResult Get() =>
ControllerContext.MyDisplayRouteInfo();
// GET api/values/5
[HttpGet("{id}")]
public IActionResult Get(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// PUT api/values/5
[HttpPut("{id}")]
public IActionResult Put(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// GET: api/values/GetValues2
[DisableCors]
[HttpGet("{action}")]
public IActionResult GetValues2() =>
ControllerContext.MyDisplayRouteInfo();
}
Der vorangehende Code:
- Aktiviert CORS nicht mit Endpunktrouting.
- Definiert keine CORS-Standardrichtlinie.
- Verwendet [EnableCors("MyPolicy")], um die CORS-Richtlinie
"MyPolicy"
für den Controller zu aktivieren. - Deaktiviert CORS für die
GetValues2
-Methode.
Anweisungen zum Testen des vorherigen Codes finden Sie unter Testen von CORS .
CORS-Richtlinienoptionen
In diesem Abschnitt werden die verschiedenen Optionen beschrieben, die in einer CORS-Richtlinie festgelegt werden können:
- Festlegen der zulässigen Ursprünge
- Festlegen der zulässigen HTTP-Methoden
- Festlegen der zulässigen Anforderungsheader
- Festlegen der verfügbar gemachten Antwortheader
- Anmeldeinformationen in ursprungsübergreifenden Anforderungen
- Festlegen der Preflight-Ablaufzeit
AddPolicy wird in Startup.ConfigureServices
aufgerufen. Für einige Optionen kann es hilfreich sein, zuerst den Abschnitt Funktionsweise von CORS zu lesen.
Festlegen der zulässigen Ursprünge
AllowAnyOrigin: Lässt CORS-Anforderungen von allen Ursprüngen mit einem beliebigen Schema (http
oder https
) zu. AllowAnyOrigin
ist unsicher, da jede Website ursprungsübergreifende Anforderungen an die App senden kann.
Hinweis
Die Angabe von AllowAnyOrigin
und AllowCredentials
ist eine unsichere Konfiguration und kann zu standortübergreifender Anforderungsfälschung führen. Der CORS-Dienst gibt eine ungültige CORS-Antwort zurück, wenn eine App mit beiden Methoden konfiguriert ist.
AllowAnyOrigin
wirkt sich auf Preflightanforderungen und den Access-Control-Allow-Origin
Header aus. Weitere Informationen finden Sie im Abschnitt Preflight-Anforderungen .
SetIsOriginAllowedToAllowWildcardSubdomains: Legt die IsOriginAllowed -Eigenschaft der Richtlinie auf eine Funktion fest, die es Ursprüngen ermöglicht, eine konfigurierte Wildcarddomäne abzugleichen, wenn ausgewertet wird, ob der Ursprung zulässig ist.
options.AddPolicy("MyAllowSubdomainPolicy",
policy =>
{
policy.WithOrigins("https://*.example.com")
.SetIsOriginAllowedToAllowWildcardSubdomains();
});
Festlegen der zulässigen HTTP-Methoden
- Ermöglicht jede HTTP-Methode:
- Wirkt sich auf Preflightanforderungen und den
Access-Control-Allow-Methods
Header aus. Weitere Informationen finden Sie im Abschnitt Preflight-Anforderungen .
Festlegen der zulässigen Anforderungsheader
Rufen Sie die zulässigen Header auf, um das Senden bestimmter Header in einer CORS-Anforderung zuzulassen, die als Autorenanforderungsheader bezeichnet werden:WithHeaders
options.AddPolicy("MyAllowHeadersPolicy",
policy =>
{
// requires using Microsoft.Net.Http.Headers;
policy.WithOrigins("http://example.com")
.WithHeaders(HeaderNames.ContentType, "x-custom-header");
});
Um alle Autorenanforderungsheader zuzulassen, rufen Sie auf AllowAnyHeader:
options.AddPolicy("MyAllowAllHeadersPolicy",
policy =>
{
policy.WithOrigins("https://*.example.com")
.AllowAnyHeader();
});
AllowAnyHeader
wirkt sich auf Preflightanforderungen und den Header Access-Control-Request-Headers aus . Weitere Informationen finden Sie im Abschnitt Preflight-Anforderungen .
Eine Übereinstimmung der CORS-Middleware-Richtlinie mit bestimmten Headern, die von WithHeaders
angegeben werden, ist nur möglich, wenn die in Access-Control-Request-Headers
gesendeten Header genau den in WithHeaders
angegebenen Headern entsprechen.
Betrachten Sie beispielsweise eine App, die wie folgt konfiguriert ist:
app.UseCors(policy => policy.WithHeaders(HeaderNames.CacheControl));
CORS-Middleware lehnt eine Preflightanforderung mit dem folgenden Anforderungsheader ab, da Content-Language
(HeaderNames.ContentLanguage) nicht in WithHeaders
aufgeführt ist:
Access-Control-Request-Headers: Cache-Control, Content-Language
Die App gibt eine 200 OK-Antwort zurück, sendet die CORS-Header jedoch nicht zurück. Daher versucht der Browser nicht, die ursprungsübergreifende Anforderung zu verwenden.
Festlegen der verfügbar gemachten Antwortheader
Standardmäßig macht der Browser nicht alle Antwortheader für die App verfügbar. Weitere Informationen finden Sie unter W3C Cross-Origin Resource Sharing (Terminologie): Einfacher Antwortheader.
Die standardmäßig verfügbaren Antwortheader sind:
Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma
Die CORS-Spezifikation ruft diese Header einfache Antwortheader auf. Rufen WithExposedHeadersSie auf, um andere Header für die App verfügbar zu machen:
options.AddPolicy("MyExposeResponseHeadersPolicy",
policy =>
{
policy.WithOrigins("https://*.example.com")
.WithExposedHeaders("x-custom-header");
});
Anmeldeinformationen in ursprungsübergreifenden Anforderungen
Anmeldeinformationen erfordern eine spezielle Behandlung in einer CORS-Anforderung. Standardmäßig sendet der Browser keine Anmeldeinformationen mit einer ursprungsübergreifenden Anforderung. Anmeldeinformationen umfassen cookies- und HTTP-Authentifizierungsschemas. Um Anmeldeinformationen mit einer ursprungsübergreifenden Anforderung zu senden, muss der Client auf true
festlegenXMLHttpRequest.withCredentials
.
Direkte Verwendung XMLHttpRequest
:
var xhr = new XMLHttpRequest();
xhr.open('get', 'https://www.example.com/api/test');
xhr.withCredentials = true;
Verwenden von jQuery:
$.ajax({
type: 'get',
url: 'https://www.example.com/api/test',
xhrFields: {
withCredentials: true
}
});
Verwenden der Fetch-API:
fetch('https://www.example.com/api/test', {
credentials: 'include'
});
Der Server muss die Anmeldeinformationen zulassen. Um ursprungsübergreifende Anmeldeinformationen zuzulassen, rufen Sie auf AllowCredentials:
options.AddPolicy("MyMyAllowCredentialsPolicy",
policy =>
{
policy.WithOrigins("http://example.com")
.AllowCredentials();
});
Die HTTP-Antwort enthält einen Access-Control-Allow-Credentials
Header, der dem Browser mitteilt, dass der Server Anmeldeinformationen für eine ursprungsübergreifende Anforderung zulässt.
Wenn der Browser Anmeldeinformationen sendet, aber die Antwort keinen gültigen Access-Control-Allow-Credentials
Header enthält, macht der Browser die Antwort für die App nicht verfügbar, und die ursprungsübergreifende Anforderung schlägt fehl.
Das Zulassen von ursprungsübergreifenden Anmeldeinformationen ist ein Sicherheitsrisiko. Eine Website in einer anderen Domäne kann die Anmeldeinformationen eines angemeldeten Benutzers im Namen des Benutzers ohne Wissen des Benutzers an die App senden.
Die CORS-Spezifikation besagt auch, dass das Festlegen von Ursprüngen auf "*"
(alle Ursprünge) ungültig ist, wenn der Access-Control-Allow-Credentials
Header vorhanden ist.
Preflight-Anforderungen
Bei einigen CORS-Anforderungen sendet der Browser vor der eigentlichen Anforderung eine zusätzliche OPTIONS-Anforderung . Diese Anforderung wird als Preflight-Anforderung bezeichnet. Der Browser kann die Preflight-Anforderung überspringen, wenn alle folgenden Bedingungen erfüllt sind:
- Die Anforderungsmethode ist GET, HEAD oder POST.
- Die App legt keine anderen Anforderungsheader als
Accept
, ,Accept-Language
Content-Language
,Content-Type
oderLast-Event-ID
fest. - Falls
Content-Type
festgelegt, weist der Header einen der folgenden Werte auf:application/x-www-form-urlencoded
multipart/form-data
text/plain
Die Für die Clientanforderung festgelegte Regel für Anforderungsheader gilt für Header, die die App durch Aufrufen setRequestHeader
des XMLHttpRequest
-Objekts festlegt. Die CORS-Spezifikation ruft diese Header zum Erstellen von Anforderungsheadern auf. Die Regel gilt nicht für Header, die der Browser festlegen kann, z User-Agent
. B. , Host
oder Content-Length
.
Im Folgenden finden Sie eine Beispielantwort, die der Preflight-Anforderung ähnelt, die über die Schaltfläche [Put test] im Abschnitt Test CORS dieses Dokuments erfolgt.
General:
Request URL: https://cors3.azurewebsites.net/api/values/5
Request Method: OPTIONS
Status Code: 204 No Content
Response Headers:
Access-Control-Allow-Methods: PUT,DELETE,GET
Access-Control-Allow-Origin: https://cors1.azurewebsites.net
Server: Microsoft-IIS/10.0
Set-Cookie: ARRAffinity=8f8...8;Path=/;HttpOnly;Domain=cors1.azurewebsites.net
Vary: Origin
Request Headers:
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Access-Control-Request-Method: PUT
Connection: keep-alive
Host: cors3.azurewebsites.net
Origin: https://cors1.azurewebsites.net
Referer: https://cors1.azurewebsites.net/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0
Die Preflight-Anforderung verwendet die HTTP OPTIONS-Methode . Es kann die folgenden Header enthalten:
- Access-Control-Request-Method: Die HTTP-Methode, die für die tatsächliche Anforderung verwendet wird.
- Access-Control-Request-Headers: Eine Liste der Anforderungsheader, die die App für die tatsächliche Anforderung festlegt. Wie bereits erwähnt, umfasst dies keine Header, die der Browser festlegt, z
User-Agent
. B. . - Access-Control-Allow-Methods
Wenn die Preflight-Anforderung verweigert wird, gibt die App eine 200 OK
Antwort zurück, legt jedoch die CORS-Header nicht fest. Daher versucht der Browser nicht, die ursprungsübergreifende Anforderung zu verwenden. Ein Beispiel für eine verweigerte Preflight-Anforderung finden Sie im Abschnitt Testen von CORS in diesem Dokument.
Bei Verwendung der F12-Tools zeigt die Konsolen-App je nach Browser einen Fehler ähnlich dem folgenden an:
- Firefox: Ursprungsübergreifende Anforderung blockiert: Die gleiche Ursprungsrichtlinie lässt das Lesen der Remoteressource unter nicht zu
https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5
. (Ursache: CORS-Anforderung war nicht erfolgreich). Weitere Informationen - Chromium basierend: Der Zugriff zum Abrufen von "https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5" vom Ursprung "https://cors3.azurewebsites.net" wurde durch cors-Richtlinie blockiert: Die Antwort auf preflight-Anforderung besteht nicht über die Zugriffssteuerungsprüfung: Für die angeforderte Ressource ist kein Header "Access-Control-Allow-Origin" vorhanden. Falls eine opake Antwort Ihre Anforderungen erfüllt, legen Sie den Modus der Anforderung auf 'no-cors' fest, um CORS für den Ressourcenabruf zu deaktivieren.
Um bestimmte Header zuzulassen, rufen Sie auf WithHeaders:
options.AddPolicy("MyAllowHeadersPolicy",
policy =>
{
// requires using Microsoft.Net.Http.Headers;
policy.WithOrigins("http://example.com")
.WithHeaders(HeaderNames.ContentType, "x-custom-header");
});
Um alle Autorenanforderungsheader zuzulassen, rufen Sie auf AllowAnyHeader:
options.AddPolicy("MyAllowAllHeadersPolicy",
policy =>
{
policy.WithOrigins("https://*.example.com")
.AllowAnyHeader();
});
Browser sind bei der Festlegung Access-Control-Request-Headers
von nicht konsistent. Wenn einer der folgenden Aktionen zu beachten ist:
- Header werden auf alle anderen Elemente als festgelegt.
"*"
- AllowAnyHeader wird aufgerufen: Schließen Sie mindestens
Accept
,Content-Type
undOrigin
sowie alle benutzerdefinierten Header ein, die Sie unterstützen möchten.
Code für automatische Preflight-Anforderung
Wenn die CORS-Richtlinie angewendet wird:
- Global durch Aufrufen
app.UseCors
von inStartup.Configure
. - Verwenden des -Attributs
[EnableCors]
.
ASP.NET Core antwortet auf die OPTIONS-Anforderung im Preflight.
Die Aktivierung von CORS pro Endpunkt mit unterstützt RequireCors
derzeit keine automatischen Preflightanforderungen.
Im Abschnitt CORS testen dieses Dokuments wird dieses Verhalten veranschaulicht.
[HttpOptions]-Attribut für Preflight-Anforderungen
Wenn CORS mit der entsprechenden Richtlinie aktiviert ist, antwortet ASP.NET Core in der Regel automatisch auf CORS-Preflight-Anforderungen. In einigen Szenarien ist dies möglicherweise nicht der Fall. Beispiel: Verwenden von CORS mit Endpunktrouting.
Der folgende Code verwendet das [HttpOptions]- Attribut, um Endpunkte für OPTIONS-Anforderungen zu erstellen:
[Route("api/[controller]")]
[ApiController]
public class TodoItems2Controller : ControllerBase
{
// OPTIONS: api/TodoItems2/5
[HttpOptions("{id}")]
public IActionResult PreflightRoute(int id)
{
return NoContent();
}
// OPTIONS: api/TodoItems2
[HttpOptions]
public IActionResult PreflightRoute()
{
return NoContent();
}
[HttpPut("{id}")]
public IActionResult PutTodoItem(int id)
{
if (id < 1)
{
return BadRequest();
}
return ControllerContext.MyDisplayRouteInfo(id);
}
Anweisungen zum Testen des vorherigen Codes finden Sie unter Testen von CORS mit Endpunktrouting und [HttpOptions].
Festlegen der Preflight-Ablaufzeit
Der Access-Control-Max-Age
Header gibt an, wie lange die Antwort auf die Preflightanforderung zwischengespeichert werden kann. Um diesen Header festzulegen, rufen Sie auf SetPreflightMaxAge:
options.AddPolicy("MySetPreflightExpirationPolicy",
policy =>
{
policy.WithOrigins("http://example.com")
.SetPreflightMaxAge(TimeSpan.FromSeconds(2520));
});
Funktionsweise von CORS
In diesem Abschnitt wird beschrieben, was in einer CORS-Anforderung auf der Ebene der HTTP-Nachrichten geschieht.
- CORS ist kein Sicherheitsfeature. CORS ist ein W3C-Standard, mit dem ein Server die Richtlinie für denselben Ursprung lockern kann.
- Beispielsweise könnte ein böswilliger Akteur Cross-Site Scripting (XSS) für Ihre Website verwenden und eine websiteübergreifende Anforderung an seine CORS-fähige Website ausführen, um Informationen zu stehlen.
- Eine API ist nicht sicherer, indem CORS zugelassen wird.
- Es liegt am Client (Browser), CORS zu erzwingen. Der Server führt die Anforderung aus und gibt die Antwort zurück. Es ist der Client, der einen Fehler zurückgibt und die Antwort blockiert. Beispielsweise zeigt eines der folgenden Tools die Serverantwort an:
- Fiddler
- Postman
- .NET HttpClient
- Einen Webbrowser, indem Sie die URL in die Adressleiste eingeben.
- Es liegt am Client (Browser), CORS zu erzwingen. Der Server führt die Anforderung aus und gibt die Antwort zurück. Es ist der Client, der einen Fehler zurückgibt und die Antwort blockiert. Beispielsweise zeigt eines der folgenden Tools die Serverantwort an:
- Es ist eine Möglichkeit für einen Server, Browsern die Ausführung einer ursprungsübergreifenden XHR - oder Fetch-API-Anforderung zu ermöglichen, die andernfalls verboten wäre.
- Browser ohne CORS können keine ursprungsübergreifenden Anforderungen ausführen. Vor CORS wurde ONP verwendet,JS um diese Einschränkung zu umgehen. JSONP verwendet nicht XHR, es verwendet das
<script>
-Tag, um die Antwort zu empfangen. Skripts dürfen ursprungsübergreifend geladen werden.
- Browser ohne CORS können keine ursprungsübergreifenden Anforderungen ausführen. Vor CORS wurde ONP verwendet,JS um diese Einschränkung zu umgehen. JSONP verwendet nicht XHR, es verwendet das
Mit der CORS-Spezifikation wurden mehrere neue HTTP-Header eingeführt, die ursprungsübergreifende Anforderungen ermöglichen. Wenn ein Browser CORS unterstützt, werden diese Header automatisch für ursprungsübergreifende Anforderungen festgelegt. Benutzerdefinierter JavaScript-Code ist nicht erforderlich, um CORS zu aktivieren.
Schaltfläche "PUT-Test" im bereitgestellten Beispiel
Im Folgenden finden Sie ein Beispiel für eine ursprungsübergreifende Anforderung über die Schaltfläche Wertetest an https://cors1.azurewebsites.net/api/values
. Der Origin
Header:
- Stellt die Domäne des Standorts bereit, der die Anforderung stellt.
- Ist erforderlich und muss sich vom Host unterscheiden.
Allgemeine Header
Request URL: https://cors1.azurewebsites.net/api/values
Request Method: GET
Status Code: 200 OK
Antwortheader
Content-Encoding: gzip
Content-Type: text/plain; charset=utf-8
Server: Microsoft-IIS/10.0
Set-Cookie: ARRAffinity=8f...;Path=/;HttpOnly;Domain=cors1.azurewebsites.net
Transfer-Encoding: chunked
Vary: Accept-Encoding
X-Powered-By: ASP.NET
Anforderungsheader
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Host: cors1.azurewebsites.net
Origin: https://cors3.azurewebsites.net
Referer: https://cors3.azurewebsites.net/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0 ...
In OPTIONS
Anforderungen legt der Server den Header AntwortheaderAccess-Control-Allow-Origin: {allowed origin}
in der Antwort fest. Beispielsweise enthält das bereitgestellte Beispieldelete [EnableCors] button OPTIONS
request die folgenden Header:
Allgemeine Header
Request URL: https://cors3.azurewebsites.net/api/TodoItems2/MyDelete2/5
Request Method: OPTIONS
Status Code: 204 No Content
Antwortheader
Access-Control-Allow-Headers: Content-Type,x-custom-header
Access-Control-Allow-Methods: PUT,DELETE,GET,OPTIONS
Access-Control-Allow-Origin: https://cors1.azurewebsites.net
Server: Microsoft-IIS/10.0
Set-Cookie: ARRAffinity=8f...;Path=/;HttpOnly;Domain=cors3.azurewebsites.net
Vary: Origin
X-Powered-By: ASP.NET
Anforderungsheader
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: DELETE
Connection: keep-alive
Host: cors3.azurewebsites.net
Origin: https://cors1.azurewebsites.net
Referer: https://cors1.azurewebsites.net/test?number=2
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0
In den obigen Antwortheadern legt der Server den Access-Control-Allow-Origin-Header in der Antwort fest. Der https://cors1.azurewebsites.net
Wert dieses Headers entspricht dem Origin
Header aus der Anforderung.
Wenn AllowAnyOrigin aufgerufen wird, wird zurückgegeben Access-Control-Allow-Origin: *
, der -Wildcard-Wert. AllowAnyOrigin
lässt jeden Ursprung zu.
Wenn die Antwort den Access-Control-Allow-Origin
Header nicht enthält, schlägt die ursprungsübergreifende Anforderung fehl. Insbesondere lässt der Browser die Anforderung nicht zu. Selbst wenn der Server eine erfolgreiche Antwort zurückgibt, stellt der Browser die Antwort nicht für die Client-App zur Verfügung.
Anzeigen von OPTIONS-Anforderungen
Standardmäßig zeigen die Browser Chrome und Edge keine OPTIONS-Anforderungen auf der Registerkarte "Netzwerk" der F12-Tools an. So zeigen Sie OPTIONS-Anforderungen in diesen Browsern an:
chrome://flags/#out-of-blink-cors
oderedge://flags/#out-of-blink-cors
- deaktivieren Sie das Flag.
- „Neu starten“.
Firefox zeigt standardmäßig OPTIONS-Anforderungen an.
CORS in IIS
Bei der Bereitstellung in IIS muss CORS vor der Windows-Authentifizierung ausgeführt werden, wenn der Server nicht für anonymen Zugriff konfiguriert ist. Um dieses Szenario zu unterstützen, muss das IIS CORS-Modul für die App installiert und konfiguriert werden.
Testen von CORS
Der Beispieldownload enthält Code zum Testen von CORS. Informationen zum Herunterladen finden Sie hier. Das Beispiel ist ein API-Projekt mit hinzugefügten Razor Seiten:
public class StartupTest2
{
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy(name: "MyPolicy",
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com",
"https://cors1.azurewebsites.net",
"https://cors3.azurewebsites.net",
"https://localhost:44398",
"https://localhost:5001")
.WithMethods("PUT", "DELETE", "GET");
});
});
services.AddControllers();
services.AddRazorPages();
}
public void Configure(IApplicationBuilder app)
{
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapRazorPages();
});
}
}
Warnung
WithOrigins("https://localhost:<port>");
sollte nur zum Testen einer Beispiel-App verwendet werden, die dem Downloadbeispielcode ähnelt.
Im Folgenden ValuesController
werden die Endpunkte für Tests bereitgestellt:
[EnableCors("MyPolicy")]
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public IActionResult Get() =>
ControllerContext.MyDisplayRouteInfo();
// GET api/values/5
[HttpGet("{id}")]
public IActionResult Get(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// PUT api/values/5
[HttpPut("{id}")]
public IActionResult Put(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// GET: api/values/GetValues2
[DisableCors]
[HttpGet("{action}")]
public IActionResult GetValues2() =>
ControllerContext.MyDisplayRouteInfo();
}
MyDisplayRouteInfo wird von dem NuGet-Paket Rick.Docs.Samples.RouteInfo bereitgestellt und zeigt Routeninformationen an.
Testen Sie den obigen Beispielcode mit einem der folgenden Ansätze:
- Verwenden Sie die bereitgestellte Beispiel-App unter https://cors3.azurewebsites.net/. Es ist nicht erforderlich, das Beispiel herunterzuladen.
- Führen Sie das Beispiel mit
dotnet run
der Standard-URL aushttps://localhost:5001
. - Führen Sie das Beispiel in Visual Studio aus, wobei der Port für die URL auf 44398 festgelegt ist
https://localhost:44398
.
Verwenden eines Browsers mit den F12-Tools:
Wählen Sie die Schaltfläche Werte aus, und überprüfen Sie die Kopfzeilen auf der Registerkarte Netzwerk .
Wählen Sie die Schaltfläche PUT-Test aus. Anweisungen zum Anzeigen der OPTIONS-Anforderung finden Sie unter Anzeigen von OPTIONS-Anforderungen . Der PUT-Test erstellt zwei Anforderungen: eine OPTIONS-Preflightanforderung und die PUT-Anforderung.
Wählen Sie die
GetValues2 [DisableCors]
Schaltfläche aus, um eine fehlerhafte CORS-Anforderung auszulösen. Wie im Dokument erwähnt, gibt die Antwort 200 success zurück, aber die CORS-Anforderung wird nicht gestellt. Wählen Sie die Registerkarte Konsole aus, um den CORS-Fehler anzuzeigen. Je nach Browser wird ein Fehler ähnlich dem folgenden angezeigt:Der Zugriff zum Abrufen vom
'https://cors1.azurewebsites.net/api/values/GetValues2'
Ursprung'https://cors3.azurewebsites.net'
wurde durch die CORS-Richtlinie blockiert: Für die angeforderte Ressource ist kein "Access-Control-Allow-Origin"-Header vorhanden. Falls eine opake Antwort Ihre Anforderungen erfüllt, legen Sie den Modus der Anforderung auf 'no-cors' fest, um CORS für den Ressourcenabruf zu deaktivieren.
CORS-fähige Endpunkte können mit einem Tool wie curl, Fiddler oder Postman getestet werden. Wenn Sie ein Tool verwenden, muss sich der Vom -Header angegebene Ursprung der Origin
Anforderung von dem Host unterscheiden, der die Anforderung empfängt. Wenn die Anforderung nicht den kreuzigen Ursprung basierend auf dem Wert des Headers Origin
aufweist:
- Es ist nicht erforderlich, dass CORS-Middleware die Anforderung verarbeitet.
- CORS-Header werden in der Antwort nicht zurückgegeben.
Der folgende Befehl verwendet curl
, um eine OPTIONS-Anforderung mit Informationen ausstellen:
curl -X OPTIONS https://cors3.azurewebsites.net/api/TodoItems2/5 -i
Testen von CORS mit Endpunktrouting und [HttpOptions]
Die Aktivierung von CORS pro Endpunkt mit unterstützt RequireCors
derzeit keineautomatischen Preflightanforderungen. Betrachten Sie den folgenden Code, der Endpunktrouting verwendet, um CORS zu aktivieren:
public class StartupEndPointBugTest
{
readonly string MyPolicy = "_myPolicy";
// .WithHeaders(HeaderNames.ContentType, "x-custom-header")
// forces browsers to require a preflight request with GET
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy(name: MyPolicy,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com",
"https://cors1.azurewebsites.net",
"https://cors3.azurewebsites.net",
"https://localhost:44398",
"https://localhost:5001")
.WithHeaders(HeaderNames.ContentType, "x-custom-header")
.WithMethods("PUT", "DELETE", "GET", "OPTIONS");
});
});
services.AddControllers();
services.AddRazorPages();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers().RequireCors(MyPolicy);
endpoints.MapRazorPages();
});
}
}
Im Folgenden TodoItems1Controller
werden Endpunkte für Tests bereitgestellt:
[Route("api/[controller]")]
[ApiController]
public class TodoItems1Controller : ControllerBase
{
// PUT: api/TodoItems1/5
[HttpPut("{id}")]
public IActionResult PutTodoItem(int id)
{
if (id < 1)
{
return Content($"ID = {id}");
}
return ControllerContext.MyDisplayRouteInfo(id);
}
// Delete: api/TodoItems1/5
[HttpDelete("{id}")]
public IActionResult MyDelete(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// GET: api/TodoItems1
[HttpGet]
public IActionResult GetTodoItems() =>
ControllerContext.MyDisplayRouteInfo();
[EnableCors]
[HttpGet("{action}")]
public IActionResult GetTodoItems2() =>
ControllerContext.MyDisplayRouteInfo();
// Delete: api/TodoItems1/MyDelete2/5
[EnableCors]
[HttpDelete("{action}/{id}")]
public IActionResult MyDelete2(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
}
Testen Sie den vorherigen Code auf der Testseite des bereitgestellten Beispiels.
Die Schaltflächen Löschen [EnableCors] und GET [EnableCors] sind erfolgreich, da die Endpunkte Preflight-Anforderungen enthalten [EnableCors]
und darauf reagieren. Bei den anderen Endpunkten tritt ein Fehler auf. Die Get-Schaltfläche schlägt fehl, da JavaScript Folgendes sendet:
headers: {
"Content-Type": "x-custom-header"
},
Im Folgenden TodoItems2Controller
werden ähnliche Endpunkte bereitgestellt, aber expliziter Code zum Reagieren auf OPTIONS-Anforderungen:
[Route("api/[controller]")]
[ApiController]
public class TodoItems2Controller : ControllerBase
{
// OPTIONS: api/TodoItems2/5
[HttpOptions("{id}")]
public IActionResult PreflightRoute(int id)
{
return NoContent();
}
// OPTIONS: api/TodoItems2
[HttpOptions]
public IActionResult PreflightRoute()
{
return NoContent();
}
[HttpPut("{id}")]
public IActionResult PutTodoItem(int id)
{
if (id < 1)
{
return BadRequest();
}
return ControllerContext.MyDisplayRouteInfo(id);
}
// [EnableCors] // Not needed as OPTIONS path provided
[HttpDelete("{id}")]
public IActionResult MyDelete(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
[EnableCors] // Rquired for this path
[HttpGet]
public IActionResult GetTodoItems() =>
ControllerContext.MyDisplayRouteInfo();
[HttpGet("{action}")]
public IActionResult GetTodoItems2() =>
ControllerContext.MyDisplayRouteInfo();
[EnableCors] // Rquired for this path
[HttpDelete("{action}/{id}")]
public IActionResult MyDelete2(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
}
Testen Sie den vorherigen Code auf der Testseite des bereitgestellten Beispiels. Wählen Sie in der Dropdownliste Controllerdie Option Preflight und dann Controller festlegen aus. Alle CORS-Aufrufe der TodoItems2Controller
Endpunkte sind erfolgreich.
Zusätzliche Ressourcen
Von Rick Anderson und Kirk Larkin
In diesem Artikel erfahren Sie, wie Sie CORS in einer ASP.NET Core-App aktivieren.
Die Browsersicherheit verhindert, dass eine Webseite Anforderungen an eine andere Domäne als diejenige stellt, die die Webseite versorgt hat. Diese Einschränkung wird als Richtlinie des gleichen Ursprungs bezeichnet. Die Richtlinie des gleichen Ursprungs verhindert, dass eine schädliche Website sensible Daten von einer anderen Website liest. Manchmal möchten Sie möglicherweise anderen Websites erlauben, ursprungsübergreifende Anforderungen an Ihre App zu senden. Weitere Informationen finden Sie im Mozilla CORS-Artikel.
Ursprungsübergreifende Ressourcenfreigabe (Cross Origin Resource Sharing , CORS):
- Ist ein W3C-Standard, der es einem Server ermöglicht, die Richtlinie für denselben Ursprung zu lockern.
- Ist kein Sicherheitsfeature, CORS lockert die Sicherheit. Eine API ist nicht sicherer, indem CORS zugelassen wird. Weitere Informationen finden Sie unter Funktionsweise von CORS.
- Ermöglicht einem Server, einige ursprungsübergreifende Anforderungen explizit zuzulassen, während andere abgelehnt werden.
- Ist sicherer und flexibler als frühere Techniken wie JSONP.
Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)
Gleicher Ursprung
Zwei URLs haben denselben Ursprung, wenn sie über identische Schemas, Hosts und Ports verfügen (RFC 6454).
Diese beiden URLs haben denselben Ursprung:
https://example.com/foo.html
https://example.com/bar.html
Diese URLs haben andere Ursprünge als die vorherigen beiden URLs:
https://example.net
: Andere Domänehttps://www.example.com/foo.html
: Andere Unterdomänehttp://example.com/foo.html
: Anderes Schemahttps://example.com:9000/foo.html
: Anderer Port
Aktivieren von CORS
Es gibt drei Möglichkeiten, CORS zu aktivieren:
- In Middleware mit einer benannten OderStandardrichtlinie.
- Verwenden von Endpunktrouting.
- Mit dem [EnableCors] -Attribut.
Die Verwendung des [EnableCors]-Attributs mit einer benannten Richtlinie bietet die beste Kontrolle bei der Begrenzung von Endpunkten, die CORS unterstützen.
Warnung
UseCors muss in der richtigen Reihenfolge aufgerufen werden. Weitere Informationen finden Sie unter Middlewarereihenfolge. Muss z. UseCors
B. vor UseResponseCaching der Verwendung UseResponseCaching
von aufgerufen werden.
Jeder Ansatz wird in den folgenden Abschnitten erläutert.
CORS mit benannter Richtlinie und Middleware
CORS-Middleware verarbeitet ursprungsübergreifende Anforderungen. Der folgende Code wendet eine CORS-Richtlinie auf alle Endpunkte der App mit den angegebenen Ursprüngen an:
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
// services.AddResponseCaching();
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors(MyAllowSpecificOrigins);
app.UseAuthorization();
app.MapControllers();
app.Run();
Der vorangehende Code:
- Legt den Richtliniennamen auf fest
_myAllowSpecificOrigins
. Der Richtlinienname ist beliebig. - Ruft die UseCors Erweiterungsmethode auf und gibt die CORS-Richtlinie
_myAllowSpecificOrigins
an.UseCors
fügt die CORS-Middleware hinzu. Der Aufruf vonUseCors
muss nachUseRouting
, aber vorUseAuthorization
platziert werden. Weitere Informationen finden Sie unter Middlewarereihenfolge. - Aufrufe AddCors mit einem Lambdaausdruck. Das Lambda nimmt ein CorsPolicyBuilder -Objekt an. Konfigurationsoptionen wie
WithOrigins
werden weiter unten in diesem Artikel beschrieben. - Aktiviert die CORS-Richtlinie
_myAllowSpecificOrigins
für alle Controllerendpunkte. Informationen zum Anwenden einer CORS-Richtlinie auf bestimmte Endpunkte finden Sie unter Endpunktrouting . - Wenn Sie die Middleware für die Antwortzwischenspeicherung verwenden, rufen Sie UseCors vor auf UseResponseCaching.
Beim Endpunktrouting muss die CORS-Middleware für die Ausführung zwischen den Aufrufen von UseRouting
und UseEndpoints
konfiguriert werden.
Anweisungen zum Testen von Code ähnlich dem vorherigen Code finden Sie unter Testen von CORS .
Der AddCors Methodenaufruf fügt CORS-Dienste zum Dienstcontainer der App hinzu:
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
// services.AddResponseCaching();
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors(MyAllowSpecificOrigins);
app.UseAuthorization();
app.MapControllers();
app.Run();
Weitere Informationen finden Sie unter CORS-Richtlinienoptionen in diesem Dokument.
Die CorsPolicyBuilder Methoden können verkettet werden, wie im folgenden Code gezeigt:
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors(MyAllowSpecificOrigins);
app.UseAuthorization();
app.MapControllers();
app.Run();
Hinweis: Die angegebene URL darf keinen nachgestellten Schrägstrich (/
) enthalten. Wenn die URL mit /
beendet wird, gibt der Vergleich zurück false
, und es wird kein Header zurückgegeben.
Reihenfolge von UseCors und UseStaticFiles
UseStaticFiles
In der Regel wird vor UseCors
aufgerufen. Apps, die JavaScript zum websiteübergreifenden Abrufen statischer Dateien verwenden, müssen vor UseStaticFiles
aufrufenUseCors
.
CORS mit Standardrichtlinie und Middleware
Der folgende hervorgehobene Code aktiviert die CORS-Standardrichtlinie:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.MapControllers();
app.Run();
Der vorangehende Code wendet die CORS-Standardrichtlinie auf alle Controllerendpunkte an.
Aktivieren von Cors mit Endpunktrouting
Beim Endpunktrouting kann CORS auf Endpunktbasis mithilfe der RequireCors Erweiterungsmethoden aktiviert werden:
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
builder.Services.AddControllers();
builder.Services.AddRazorPages();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/echo",
context => context.Response.WriteAsync("echo"))
.RequireCors(MyAllowSpecificOrigins);
endpoints.MapControllers()
.RequireCors(MyAllowSpecificOrigins);
endpoints.MapGet("/echo2",
context => context.Response.WriteAsync("echo2"));
endpoints.MapRazorPages();
});
app.Run();
Für den Code oben gilt:
app.UseCors
aktiviert die CORS-Middleware. Da keine Standardrichtlinie konfiguriert wurde,app.UseCors()
wird CORS allein nicht aktiviert.- Die
/echo
Controllerendpunkte und ermöglichen ursprungsübergreifende Anforderungen mithilfe der angegebenen Richtlinie. - Die
/echo2
Pages-Endpunkte und Razor lassen ursprungsübergreifende Anforderungen nicht zu, da keine Standardrichtlinie angegeben wurde.
Das [DisableCors] -Attribut deaktiviert cors nicht , das durch Endpunktrouting mit RequireCors
aktiviert wurde.
In ASP.NET Core 7.0 muss das [EnableCors]
Attribut einen Parameter übergeben, oder eine ASP0023-Warnung wird aus einer mehrdeutigen Übereinstimmung auf der Route generiert. ASP.NET Core Version 8.0 und höher generiert die ASP0023
Warnung nicht.
[Route("api/[controller]")]
[ApiController]
public class TodoItems2Controller : ControllerBase
{
// OPTIONS: api/TodoItems2/5
[HttpOptions("{id}")]
public IActionResult PreflightRoute(int id)
{
return NoContent();
}
// OPTIONS: api/TodoItems2
[HttpOptions]
public IActionResult PreflightRoute()
{
return NoContent();
}
[HttpPut("{id}")]
public IActionResult PutTodoItem(int id)
{
if (id < 1)
{
return BadRequest();
}
return ControllerContext.MyDisplayRouteInfo(id);
}
// [EnableCors] // Not needed as OPTIONS path provided.
[HttpDelete("{id}")]
public IActionResult MyDelete(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// [EnableCors] // Warning ASP0023 Route '{id}' conflicts with another action route.
// An HTTP request that matches multiple routes results in an ambiguous
// match error.
[EnableCors("MyPolicy")] // Required for this path.
[HttpGet]
public IActionResult GetTodoItems() =>
ControllerContext.MyDisplayRouteInfo();
[HttpGet("{action}")]
public IActionResult GetTodoItems2() =>
ControllerContext.MyDisplayRouteInfo();
[EnableCors("MyPolicy")] // Required for this path.
[HttpDelete("{action}/{id}")]
public IActionResult MyDelete2(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
}
Anweisungen zum Testen von Code finden Sie unter Testen von CORS mit dem [EnableCors]-Attribut und der RequireCors-Methode .
Aktivieren von CORS mit Attributen
Das Aktivieren von CORS mit dem [EnableCors]- Attribut und das Anwenden einer benannten Richtlinie nur auf die Endpunkte, die CORS erfordern, bietet die beste Steuerung.
Das Attribut [EnableCors] bietet eine Alternative zum globalen Anwenden von CORS. Das [EnableCors]
Attribut aktiviert CORS für ausgewählte Endpunkte und nicht für alle Endpunkte:
[EnableCors]
gibt die Standardrichtlinie an.[EnableCors("{Policy String}")]
gibt eine benannte Richtlinie an.
Das [EnableCors]
Attribut kann auf Folgendes angewendet werden:
- Razor Seite
PageModel
- Controller
- Controlleraktionsmethode
Mit dem [EnableCors]
-Attribut können verschiedene Richtlinien auf Controller, Seitenmodelle oder Aktionsmethoden angewendet werden. Wenn das [EnableCors]
Attribut auf einen Controller, ein Seitenmodell oder eine Aktionsmethode angewendet wird und CORS in der Middleware aktiviert ist, werden beide Richtlinien angewendet. Es wird empfohlen, Richtlinien nicht zu kombinieren. Verwenden Sie die Schaltfläche [EnableCors]
Attribut oder Middleware, nicht beides in derselben App.
Der folgende Code wendet eine andere Richtlinie auf jede Methode an:
[Route("api/[controller]")]
[ApiController]
public class WidgetController : ControllerBase
{
// GET api/values
[EnableCors("AnotherPolicy")]
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { "green widget", "red widget" };
}
// GET api/values/5
[EnableCors("Policy1")]
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
return id switch
{
1 => "green widget",
2 => "red widget",
_ => NotFound(),
};
}
}
Der folgende Code erstellt zwei CORS-Richtlinien:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("Policy1",
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com");
});
options.AddPolicy("AnotherPolicy",
policy =>
{
policy.WithOrigins("http://www.contoso.com")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.MapControllers();
app.Run();
Für die beste Kontrolle der Begrenzung von CORS-Anforderungen:
- Verwenden Sie
[EnableCors("MyPolicy")]
mit einer benannten Richtlinie. - Definieren Sie keine Standardrichtlinie.
- Verwenden Sie kein Endpunktrouting.
Der Code im nächsten Abschnitt entspricht der vorherigen Liste.
Anweisungen zum Testen von Code, der dem vorherigen Code ähnelt, finden Sie unter Testen von CORS .
Deaktivieren von CORS
Das [DisableCors] -Attribut deaktiviert keine CORS, die durch Endpunktrouting aktiviert wurde.
Der folgende Code definiert die CORS-Richtlinie "MyPolicy"
:
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: "MyPolicy",
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com")
.WithMethods("PUT", "DELETE", "GET");
});
});
builder.Services.AddControllers();
builder.Services.AddRazorPages();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.UseEndpoints(endpoints => {
endpoints.MapControllers();
endpoints.MapRazorPages();
});
app.Run();
Der folgende Code deaktiviert CORS für die GetValues2
Aktion:
[EnableCors("MyPolicy")]
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public IActionResult Get() =>
ControllerContext.MyDisplayRouteInfo();
// GET api/values/5
[HttpGet("{id}")]
public IActionResult Get(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// PUT api/values/5
[HttpPut("{id}")]
public IActionResult Put(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// GET: api/values/GetValues2
[DisableCors]
[HttpGet("{action}")]
public IActionResult GetValues2() =>
ControllerContext.MyDisplayRouteInfo();
}
Der vorangehende Code:
- Aktiviert CORS nicht mit Endpunktrouting.
- Definiert keine CORS-Standardrichtlinie.
- Verwendet [EnableCors("MyPolicy")], um die CORS-Richtlinie
"MyPolicy"
für den Controller zu aktivieren. - Deaktiviert CORS für die
GetValues2
-Methode.
Anweisungen zum Testen des vorherigen Codes finden Sie unter Testen von CORS .
CORS-Richtlinienoptionen
In diesem Abschnitt werden die verschiedenen Optionen beschrieben, die in einer CORS-Richtlinie festgelegt werden können:
- Festlegen der zulässigen Ursprünge
- Festlegen der zulässigen HTTP-Methoden
- Festlegen der zulässigen Anforderungsheader
- Festlegen der verfügbar gemachten Antwortheader
- Anmeldeinformationen in ursprungsübergreifenden Anforderungen
- Festlegen der Preflight-Ablaufzeit
AddPolicy wird in Program.cs
aufgerufen. Für einige Optionen kann es hilfreich sein, zuerst den Abschnitt Funktionsweise von CORS zu lesen.
Festlegen der zulässigen Ursprünge
AllowAnyOrigin: Ermöglicht CORS-Anforderungen aus allen Ursprüngen mit einem beliebigen Schema (http
oder https
). AllowAnyOrigin
ist unsicher, da jede Website ursprungsübergreifende Anforderungen an die App stellen kann.
Hinweis
Die Angabe von AllowAnyOrigin
und AllowCredentials
ist eine unsichere Konfiguration und kann zu standortübergreifender Anforderungsfälschung führen. Der CORS-Dienst gibt eine ungültige CORS-Antwort zurück, wenn eine App mit beiden Methoden konfiguriert ist.
AllowAnyOrigin
wirkt sich auf Preflight-Anforderungen und den Access-Control-Allow-Origin
Header aus. Weitere Informationen finden Sie im Abschnitt Preflight-Anforderungen .
SetIsOriginAllowedToAllowWildcardSubdomains: Legt die IsOriginAllowed -Eigenschaft der Richtlinie als Funktion fest, die es Ursprüngen ermöglicht, einer konfigurierten Feldhalterdomäne bei der Bewertung zu entsprechen, ob der Ursprung zulässig ist.
var MyAllowSpecificOrigins = "_MyAllowSubdomainPolicy";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("https://*.example.com")
.SetIsOriginAllowedToAllowWildcardSubdomains();
});
});
builder.Services.AddControllers();
var app = builder.Build();
Festlegen der zulässigen HTTP-Methoden
- Ermöglicht jede HTTP-Methode:
- Wirkt sich auf Preflight-Anforderungen und den
Access-Control-Allow-Methods
Header aus. Weitere Informationen finden Sie im Abschnitt Preflight-Anforderungen .
Festlegen der zulässigen Anforderungsheader
Rufen WithHeaders Sie die zulässigen Header auf, um das Senden bestimmter Header in einer CORS-Anforderung als Autorenanforderungsheader zuzulassen:
using Microsoft.Net.Http.Headers;
var MyAllowSpecificOrigins = "_MyAllowSubdomainPolicy";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://example.com")
.WithHeaders(HeaderNames.ContentType, "x-custom-header");
});
});
builder.Services.AddControllers();
var app = builder.Build();
Rufen Sie zum Zulassen aller Autorenanforderungsheader auf AllowAnyHeader:
var MyAllowSpecificOrigins = "_MyAllowSubdomainPolicy";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("https://*.example.com")
.AllowAnyHeader();
});
});
builder.Services.AddControllers();
var app = builder.Build();
AllowAnyHeader
wirkt sich auf Preflight-Anforderungen und den Access-Control-Request-Headers-Headers aus. Weitere Informationen finden Sie im Abschnitt Preflight-Anforderungen .
Eine Übereinstimmung der CORS-Middleware-Richtlinie mit bestimmten Headern, die durch WithHeaders
angegeben werden, ist nur möglich, wenn die gesendeten Access-Control-Request-Headers
Header genau mit den in WithHeaders
angegebenen Headern übereinstimmen.
Betrachten Sie beispielsweise eine App, die wie folgt konfiguriert ist:
app.UseCors(policy => policy.WithHeaders(HeaderNames.CacheControl));
CORS Middleware lehnt eine Preflight-Anforderung mit dem folgenden Anforderungsheader ab, da Content-Language
(HeaderNames.ContentLanguage) nicht in WithHeaders
aufgeführt ist:
Access-Control-Request-Headers: Cache-Control, Content-Language
Die App gibt eine Antwort mit 200 OK zurück, sendet die CORS-Header jedoch nicht zurück. Daher versucht der Browser die ursprungsübergreifende Anforderung nicht.
Festlegen der verfügbar gemachten Antwortheader
Standardmäßig macht der Browser nicht alle Antwortheader für die App verfügbar. Weitere Informationen finden Sie unter W3C Cross-Origin Resource Sharing (Terminologie): Einfacher Antwortheader.
Standardmäßig sind folgende Antwortheader verfügbar:
Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma
Die CORS-Spezifikation ruft diese Header als einfache Antwortheader auf. Rufen Sie folgendes auf WithExposedHeaders, um andere Header für die App verfügbar zu machen:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MyExposeResponseHeadersPolicy",
policy =>
{
policy.WithOrigins("https://*.example.com")
.WithExposedHeaders("x-custom-header");
});
});
builder.Services.AddControllers();
var app = builder.Build();
Anmeldeinformationen in ursprungsübergreifenden Anforderungen
Anmeldeinformationen erfordern eine spezielle Behandlung in einer CORS-Anforderung. Standardmäßig sendet der Browser keine Anmeldeinformationen mit einer ursprungsübergreifenden Anforderung. Anmeldeinformationen umfassen cookies- und HTTP-Authentifizierungsschemas. Um Anmeldeinformationen mit einer ursprungsübergreifenden Anforderung zu senden, muss der Client auf true
festlegenXMLHttpRequest.withCredentials
.
Direkte Verwendung XMLHttpRequest
:
var xhr = new XMLHttpRequest();
xhr.open('get', 'https://www.example.com/api/test');
xhr.withCredentials = true;
Verwenden von jQuery:
$.ajax({
type: 'get',
url: 'https://www.example.com/api/test',
xhrFields: {
withCredentials: true
}
});
Verwenden der Abruf-API:
fetch('https://www.example.com/api/test', {
credentials: 'include'
});
Der Server muss die Anmeldeinformationen zulassen. Um ursprungsübergreifende Anmeldeinformationen zuzulassen, rufen Sie folgendes auf AllowCredentials:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MyMyAllowCredentialsPolicy",
policy =>
{
policy.WithOrigins("http://example.com")
.AllowCredentials();
});
});
builder.Services.AddControllers();
var app = builder.Build();
Die HTTP-Antwort enthält einen Access-Control-Allow-Credentials
Header, der dem Browser mitteilt, dass der Server Anmeldeinformationen für eine ursprungsübergreifende Anforderung zulässt.
Wenn der Browser Anmeldeinformationen sendet, die Antwort aber keinen gültigen Access-Control-Allow-Credentials
Header enthält, macht der Browser die Antwort für die App nicht verfügbar, und die ursprungsübergreifende Anforderung schlägt fehl.
Das Zulassen von ursprungsübergreifenden Anmeldeinformationen ist ein Sicherheitsrisiko. Eine Website in einer anderen Domäne kann die Anmeldeinformationen eines angemeldeten Benutzers im Namen des Benutzers ohne Wissen des Benutzers an die App senden.
Die CORS-Spezifikation besagt auch, dass das Festlegen von Ursprüngen auf "*"
(alle Ursprünge) ungültig ist, wenn der Access-Control-Allow-Credentials
Header vorhanden ist.
Preflight-Anforderungen
Bei einigen CORS-Anforderungen sendet der Browser vor der eigentlichen Anforderung eine zusätzliche OPTIONS-Anforderung . Diese Anforderung wird als Preflight-Anforderung bezeichnet. Der Browser kann die Preflight-Anforderung überspringen, wenn alle folgenden Bedingungen erfüllt sind:
- Die Anforderungsmethode ist GET, HEAD oder POST.
- Die App legt keine anderen Anforderungsheader als
Accept
, ,Accept-Language
Content-Language
,Content-Type
oderLast-Event-ID
fest. - Falls festgelegt, weist der
Content-Type
Header einen der folgenden Werte auf:application/x-www-form-urlencoded
multipart/form-data
text/plain
Die Für die Clientanforderung festgelegte Regel für Anforderungsheader gilt für Header, die die App durch Aufrufen setRequestHeader
des XMLHttpRequest
-Objekts festlegt. Die CORS-Spezifikation ruft diese Header für Autorenanforderungsheader auf. Die Regel gilt nicht für Header, die der Browser festlegen kann, z User-Agent
. B. , Host
oder Content-Length
.
Die folgende Beispielantwort ähnelt der Preflight-Anforderung über die Schaltfläche [Test ablegen] im Abschnitt CORS testen dieses Dokuments.
General:
Request URL: https://cors3.azurewebsites.net/api/values/5
Request Method: OPTIONS
Status Code: 204 No Content
Response Headers:
Access-Control-Allow-Methods: PUT,DELETE,GET
Access-Control-Allow-Origin: https://cors1.azurewebsites.net
Server: Microsoft-IIS/10.0
Set-Cookie: ARRAffinity=8f8...8;Path=/;HttpOnly;Domain=cors1.azurewebsites.net
Vary: Origin
Request Headers:
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Access-Control-Request-Method: PUT
Connection: keep-alive
Host: cors3.azurewebsites.net
Origin: https://cors1.azurewebsites.net
Referer: https://cors1.azurewebsites.net/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0
Die Preflight-Anforderung verwendet die HTTP OPTIONS-Methode . Es kann die folgenden Header enthalten:
- Access-Control-Request-Method: Die HTTP-Methode, die für die tatsächliche Anforderung verwendet wird.
- Access-Control-Request-Headers: Eine Liste der Anforderungsheader, die die App für die tatsächliche Anforderung festlegt. Wie bereits erwähnt, enthält dies keine Header, die vom Browser festgelegt werden, z. B
User-Agent
. . - Access-Control-Allow-Methods
Wenn die Preflight-Anforderung abgelehnt wird, gibt die App eine 200 OK
Antwort zurück, legt aber die CORS-Header nicht fest. Daher versucht der Browser die ursprungsübergreifende Anforderung nicht. Ein Beispiel für eine verweigerte Preflight-Anforderung finden Sie im Abschnitt CORS-Test dieses Dokuments.
Bei Verwendung der F12-Tools zeigt die Konsolen-App je nach Browser einen Fehler ähnlich einem der folgenden an:
- Firefox: Cross-Origin Request Blockiert: Die gleiche Ursprungsrichtlinie lässt das Lesen der Remoteressource unter nicht zu
https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5
. (Grund: CORS-Anforderung war nicht erfolgreich). Weitere Informationen - Chromium basiert: Der Zugriff auf den Abruf von "https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5" vom Ursprung "https://cors3.azurewebsites.net" wurde durch die CORS-Richtlinie blockiert: Die Antwort auf eine Preflight-Anforderung besteht nicht über die Zugriffssteuerungsprüfung: Für die angeforderte Ressource ist kein "Access-Control-Allow-Origin"-Header vorhanden. Falls eine opake Antwort Ihre Anforderungen erfüllt, legen Sie den Modus der Anforderung auf 'no-cors' fest, um CORS für den Ressourcenabruf zu deaktivieren.
Um bestimmte Header zuzulassen, rufen Sie folgendes auf WithHeaders:
using Microsoft.Net.Http.Headers;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MyAllowHeadersPolicy",
policy =>
{
policy.WithOrigins("http://example.com")
.WithHeaders(HeaderNames.ContentType, "x-custom-header");
});
});
builder.Services.AddControllers();
var app = builder.Build();
Rufen Sie zum Zulassen aller Autorenanforderungsheader auf AllowAnyHeader:
using Microsoft.Net.Http.Headers;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MyAllowAllHeadersPolicy",
policy =>
{
policy.WithOrigins("https://*.example.com")
.AllowAnyHeader();
});
});
builder.Services.AddControllers();
var app = builder.Build();
Browser sind nicht konsistent, wenn sie festlegen Access-Control-Request-Headers
. Wenn einer der folgenden Aktionen zu beachten ist:
- Header sind auf alles andere als festgelegt.
"*"
- AllowAnyHeader wird aufgerufen: Schließen Sie mindestens
Accept
,Content-Type
undOrigin
sowie alle benutzerdefinierten Header ein, die Sie unterstützen möchten.
Code für automatische Preflight-Anforderungen
Wenn die CORS-Richtlinie angewendet wird:
- Global, indem Sie in
Program.cs
aufrufenapp.UseCors
. - Verwenden des -Attributs
[EnableCors]
.
ASP.NET Core antwortet auf die Preflight OPTIONS-Anforderung.
Im Abschnitt CORS-Test dieses Dokuments wird dieses Verhalten veranschaulicht.
[HttpOptions]-Attribut für Preflight-Anforderungen
Wenn CORS mit der entsprechenden Richtlinie aktiviert ist, reagiert ASP.NET Core in der Regel automatisch auf CORS-Preflight-Anforderungen.
Der folgende Code verwendet das [HttpOptions]- Attribut, um Endpunkte für OPTIONS-Anforderungen zu erstellen:
[Route("api/[controller]")]
[ApiController]
public class TodoItems2Controller : ControllerBase
{
// OPTIONS: api/TodoItems2/5
[HttpOptions("{id}")]
public IActionResult PreflightRoute(int id)
{
return NoContent();
}
// OPTIONS: api/TodoItems2
[HttpOptions]
public IActionResult PreflightRoute()
{
return NoContent();
}
[HttpPut("{id}")]
public IActionResult PutTodoItem(int id)
{
if (id < 1)
{
return BadRequest();
}
return ControllerContext.MyDisplayRouteInfo(id);
}
Anweisungen zum Testen des vorherigen Codes finden Sie unter Testen von CORS mit dem Attribut [EnableCors] und der RequireCors-Methode .
Festlegen der Preflight-Ablaufzeit
Der Access-Control-Max-Age
Header gibt an, wie lange die Antwort auf die Preflight-Anforderung zwischengespeichert werden kann. Rufen Sie zum Festlegen dieses Headers auf SetPreflightMaxAge:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MySetPreflightExpirationPolicy",
policy =>
{
policy.WithOrigins("http://example.com")
.SetPreflightMaxAge(TimeSpan.FromSeconds(2520));
});
});
builder.Services.AddControllers();
var app = builder.Build();
Aktivieren von CORS auf einem Endpunkt
Funktionsweise von CORS
In diesem Abschnitt wird beschrieben, was in einer CORS-Anforderung auf der Ebene der HTTP-Nachrichten geschieht.
- CORS ist kein Sicherheitsfeature. CORS ist ein W3C-Standard, der es einem Server ermöglicht, die Richtlinie desselben Ursprungs zu lockern.
- Beispielsweise kann ein böswilliger Akteur Cross-Site Scripting (XSS) für Ihre Website verwenden und eine websiteübergreifende Anforderung an seine CORS-fähige Website ausführen, um Informationen zu stehlen.
- Eine API ist nicht sicherer, indem CORS zugelassen wird.
- Es liegt am Client (Browser), CORS zu erzwingen. Der Server führt die Anforderung aus und gibt die Antwort zurück. Es ist der Client, der einen Fehler zurückgibt und die Antwort blockiert. Beispielsweise zeigt eines der folgenden Tools die Serverantwort an:
- Fiddler
- Postman
- .NET HttpClient
- Ein Webbrowser, indem Sie die URL in die Adressleiste eingeben.
- Es liegt am Client (Browser), CORS zu erzwingen. Der Server führt die Anforderung aus und gibt die Antwort zurück. Es ist der Client, der einen Fehler zurückgibt und die Antwort blockiert. Beispielsweise zeigt eines der folgenden Tools die Serverantwort an:
- Es ist eine Möglichkeit für einen Server, Browsern zu erlauben, eine ursprungsübergreifende XHR - oder Fetch-API-Anforderung auszuführen, die andernfalls verboten wäre.
- Browser ohne CORS können keine ursprungsübergreifenden Anforderungen ausführen. Vor CORS wurde ONP verwendet,JS um diese Einschränkung zu umgehen. JSONP verwendet nicht XHR, es verwendet das
<script>
-Tag, um die Antwort zu empfangen. Skripts dürfen ursprungsübergreifend geladen werden.
- Browser ohne CORS können keine ursprungsübergreifenden Anforderungen ausführen. Vor CORS wurde ONP verwendet,JS um diese Einschränkung zu umgehen. JSONP verwendet nicht XHR, es verwendet das
Mit der CORS-Spezifikation wurden mehrere neue HTTP-Header eingeführt, die ursprungsübergreifende Anforderungen ermöglichen. Wenn ein Browser CORS unterstützt, legt er diese Header automatisch für ursprungsübergreifende Anforderungen fest. Benutzerdefinierter JavaScript-Code ist nicht erforderlich, um CORS zu aktivieren.
Die SCHALTFLÄCHE PUT-Test im bereitgestellten Beispiel
Im Folgenden wird ein Beispiel für eine ursprungsübergreifende Anforderung von der Schaltfläche Wertetest an angezeigt https://cors1.azurewebsites.net/api/values
. Der Origin
Header:
- Stellt die Domäne des Standorts bereit, der die Anforderung stellt.
- Ist erforderlich und muss sich vom Host unterscheiden.
Allgemeine Header
Request URL: https://cors1.azurewebsites.net/api/values
Request Method: GET
Status Code: 200 OK
Antwortheader
Content-Encoding: gzip
Content-Type: text/plain; charset=utf-8
Server: Microsoft-IIS/10.0
Set-Cookie: ARRAffinity=8f...;Path=/;HttpOnly;Domain=cors1.azurewebsites.net
Transfer-Encoding: chunked
Vary: Accept-Encoding
X-Powered-By: ASP.NET
Anforderungsheader
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Host: cors1.azurewebsites.net
Origin: https://cors3.azurewebsites.net
Referer: https://cors3.azurewebsites.net/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0 ...
In OPTIONS
Anforderungen legt der Server den Header AntwortheaderAccess-Control-Allow-Origin: {allowed origin}
in der Antwort fest. Beispielsweise enthält das bereitgestellte Beispieldie SchaltflächenanforderungOPTIONS
löschen [EnableCors] die folgenden Header:
Allgemeine Header
Request URL: https://cors3.azurewebsites.net/api/TodoItems2/MyDelete2/5
Request Method: OPTIONS
Status Code: 204 No Content
Antwortheader
Access-Control-Allow-Headers: Content-Type,x-custom-header
Access-Control-Allow-Methods: PUT,DELETE,GET,OPTIONS
Access-Control-Allow-Origin: https://cors1.azurewebsites.net
Server: Microsoft-IIS/10.0
Set-Cookie: ARRAffinity=8f...;Path=/;HttpOnly;Domain=cors3.azurewebsites.net
Vary: Origin
X-Powered-By: ASP.NET
Anforderungsheader
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: DELETE
Connection: keep-alive
Host: cors3.azurewebsites.net
Origin: https://cors1.azurewebsites.net
Referer: https://cors1.azurewebsites.net/test?number=2
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0
In den vorherigen Antwortheadern legt der Server den Access-Control-Allow-Origin-Header in der Antwort fest. Der https://cors1.azurewebsites.net
Wert dieses Headers entspricht dem Origin
Header aus der Anforderung.
Wenn AllowAnyOrigin aufgerufen wird, wird der Access-Control-Allow-Origin: *
, der Feldhalterwert, zurückgegeben. AllowAnyOrigin
lässt jeden Ursprung zu.
Wenn die Antwort den Header nicht enthält Access-Control-Allow-Origin
, schlägt die ursprungsübergreifende Anforderung fehl. Insbesondere lässt der Browser die Anforderung nicht zu. Auch wenn der Server eine erfolgreiche Antwort zurückgibt, stellt der Browser die Antwort nicht für die Client-App zur Verfügung.
HTTP-Umleitung zu HTTPS verursacht ERR_INVALID_REDIRECT für die CORS-Preflight-Anforderung
Anforderungen an einen Endpunkt mithilfe von UseHttpsRedirection HTTP, die an HTTPS weitergeleitet werden, schlagen mit ERR_INVALID_REDIRECT on the CORS preflight request
fehl.
API-Projekte können HTTP-Anforderungen ablehnen, anstatt UseHttpsRedirection
Anforderungen an HTTPS umzuleiten.
CORS in IIS
Bei der Bereitstellung in IIS muss CORS vor der Windows-Authentifizierung ausgeführt werden, wenn der Server nicht für den anonymen Zugriff konfiguriert ist. Um dieses Szenario zu unterstützen, muss das IIS CORS-Modul installiert und für die App konfiguriert werden.
Testen von CORS
Der Beispieldownload enthält Code zum Testen von CORS. Informationen zum Herunterladen finden Sie hier. Das Beispiel ist ein API-Projekt mit Razor hinzugefügten Seiten:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: "MyPolicy",
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com",
"https://cors1.azurewebsites.net",
"https://cors3.azurewebsites.net",
"https://localhost:44398",
"https://localhost:5001")
.WithMethods("PUT", "DELETE", "GET");
});
});
builder.Services.AddControllers();
builder.Services.AddRazorPages();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.MapControllers();
app.MapRazorPages();
app.Run();
Warnung
WithOrigins("https://localhost:<port>");
sollte nur zum Testen einer Beispiel-App verwendet werden, die dem Downloadbeispielcode ähnelt.
Im Folgenden ValuesController
werden die Endpunkte für Tests bereitgestellt:
[EnableCors("MyPolicy")]
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public IActionResult Get() =>
ControllerContext.MyDisplayRouteInfo();
// GET api/values/5
[HttpGet("{id}")]
public IActionResult Get(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// PUT api/values/5
[HttpPut("{id}")]
public IActionResult Put(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// GET: api/values/GetValues2
[DisableCors]
[HttpGet("{action}")]
public IActionResult GetValues2() =>
ControllerContext.MyDisplayRouteInfo();
}
MyDisplayRouteInfo wird von dem NuGet-Paket Rick.Docs.Samples.RouteInfo bereitgestellt und zeigt Routeninformationen an.
Testen Sie den vorherigen Beispielcode mit einem der folgenden Ansätze:
- Verwenden Sie die bereitgestellte Beispiel-App unter https://cors3.azurewebsites.net/. Das Beispiel muss nicht heruntergeladen werden.
- Führen Sie das Beispiel mit
dotnet run
der Standard-URL von aushttps://localhost:5001
. - Führen Sie das Beispiel in Visual Studio aus, wobei der Port auf 44398 für eine URL von
https://localhost:44398
festgelegt ist.
Verwenden eines Browsers mit den F12-Tools:
Wählen Sie die Schaltfläche Werte aus, und überprüfen Sie die Header auf der Registerkarte Netzwerk .
Wählen Sie die Schaltfläche PUT-Test aus. Anweisungen zum Anzeigen der OPTIONS-Anforderung finden Sie unter Anzeigen von OPTIONS-Anforderungen . Der PUT-Test erstellt zwei Anforderungen, eine OPTIONS-Preflight-Anforderung und die PUT-Anforderung.
Wählen Sie die
GetValues2 [DisableCors]
Schaltfläche aus, um eine fehlerhafte CORS-Anforderung auszulösen. Wie im Dokument erwähnt, gibt die Antwort 200 erfolgreich zurück, aber die CORS-Anforderung wird nicht gestellt. Wählen Sie die Registerkarte Konsole aus, um den CORS-Fehler anzuzeigen. Je nach Browser wird ein Fehler ähnlich dem folgenden angezeigt:Der Zugriff auf
'https://cors1.azurewebsites.net/api/values/GetValues2'
den Abruf vom Ursprung'https://cors3.azurewebsites.net'
wurde durch die CORS-Richtlinie blockiert: Für die angeforderte Ressource ist kein "Access-Control-Allow-Origin"-Header vorhanden. Falls eine opake Antwort Ihre Anforderungen erfüllt, legen Sie den Modus der Anforderung auf 'no-cors' fest, um CORS für den Ressourcenabruf zu deaktivieren.
CORS-fähige Endpunkte können mit einem Tool wie curl, Fiddler oder Postman getestet werden. Bei Verwendung eines Tools muss sich der Ursprung der durch den Origin
Header angegebenen Anforderung von dem Host unterscheiden, der die Anforderung empfängt. Wenn die Anforderung nicht originsübergreifend ist, basierend auf dem Wert des Origin
Headers:
- Cors Middleware muss die Anforderung nicht verarbeiten.
- CORS-Header werden in der Antwort nicht zurückgegeben.
Der folgende Befehl verwendet curl
, um eine OPTIONS-Anforderung mit Informationen ausstellen zu können:
curl -X OPTIONS https://cors3.azurewebsites.net/api/TodoItems2/5 -i
Testen von CORS mit dem Attribut [EnableCors] und der RequireCors-Methode
Betrachten Sie den folgenden Code, der Endpunktrouting verwendet, um CORS pro Endpunkt zu aktivieren:RequireCors
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: "MyPolicy",
policy =>
{
policy.WithOrigins("http://example.com",
"http://www.contoso.com",
"https://cors1.azurewebsites.net",
"https://cors3.azurewebsites.net",
"https://localhost:44398",
"https://localhost:5001")
.WithMethods("PUT", "DELETE", "GET");
});
});
builder.Services.AddControllers();
builder.Services.AddRazorPages();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/echo",
context => context.Response.WriteAsync("echo"))
.RequireCors("MyPolicy");
endpoints.MapControllers();
endpoints.MapRazorPages();
});
app.Run();
Beachten Sie, dass nur der /echo
Endpunkt verwendet, RequireCors
um ursprungsübergreifende Anforderungen mithilfe der angegebenen Richtlinie zuzulassen. Die folgenden Controller aktivieren CORS mit dem Attribut [EnableCors].
Im Folgenden TodoItems1Controller
werden Endpunkte für Tests bereitgestellt:
[Route("api/[controller]")]
[ApiController]
public class TodoItems1Controller : ControllerBase
{
// PUT: api/TodoItems1/5
[HttpPut("{id}")]
public IActionResult PutTodoItem(int id) {
if (id < 1) {
return Content($"ID = {id}");
}
return ControllerContext.MyDisplayRouteInfo(id);
}
// Delete: api/TodoItems1/5
[HttpDelete("{id}")]
public IActionResult MyDelete(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// GET: api/TodoItems1
[HttpGet]
public IActionResult GetTodoItems() =>
ControllerContext.MyDisplayRouteInfo();
[EnableCors("MyPolicy")]
[HttpGet("{action}")]
public IActionResult GetTodoItems2() =>
ControllerContext.MyDisplayRouteInfo();
// Delete: api/TodoItems1/MyDelete2/5
[EnableCors("MyPolicy")]
[HttpDelete("{action}/{id}")]
public IActionResult MyDelete2(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
}
Testen Sie den vorherigen Code auf der Testseite des bereitgestellten Beispiels.
Die Schaltflächen Löschen [EnableCors] und GET [EnableCors] sind erfolgreich, da die Endpunkte Preflight-Anforderungen enthalten [EnableCors]
und darauf reagieren. Bei den anderen Endpunkten tritt ein Fehler auf. Die Schaltfläche GET schlägt fehl, da JavaScript Folgendes sendet:
headers: {
"Content-Type": "x-custom-header"
},
Das Folgende TodoItems2Controller
bietet ähnliche Endpunkte, enthält jedoch expliziten Code, um auf OPTIONS-Anforderungen zu reagieren:
[Route("api/[controller]")]
[ApiController]
public class TodoItems2Controller : ControllerBase
{
// OPTIONS: api/TodoItems2/5
[HttpOptions("{id}")]
public IActionResult PreflightRoute(int id)
{
return NoContent();
}
// OPTIONS: api/TodoItems2
[HttpOptions]
public IActionResult PreflightRoute()
{
return NoContent();
}
[HttpPut("{id}")]
public IActionResult PutTodoItem(int id)
{
if (id < 1)
{
return BadRequest();
}
return ControllerContext.MyDisplayRouteInfo(id);
}
// [EnableCors] // Not needed as OPTIONS path provided.
[HttpDelete("{id}")]
public IActionResult MyDelete(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
// [EnableCors] // Warning ASP0023 Route '{id}' conflicts with another action route.
// An HTTP request that matches multiple routes results in an ambiguous
// match error.
[EnableCors("MyPolicy")] // Required for this path.
[HttpGet]
public IActionResult GetTodoItems() =>
ControllerContext.MyDisplayRouteInfo();
[HttpGet("{action}")]
public IActionResult GetTodoItems2() =>
ControllerContext.MyDisplayRouteInfo();
[EnableCors("MyPolicy")] // Required for this path.
[HttpDelete("{action}/{id}")]
public IActionResult MyDelete2(int id) =>
ControllerContext.MyDisplayRouteInfo(id);
}
Testen Sie den vorherigen Code auf der Testseite des bereitgestellten Beispiels. Wählen Sie in der Dropdownliste Controllerdie Option Preflight und dann Controller festlegen aus. Alle CORS-Aufrufe der TodoItems2Controller
Endpunkte sind erfolgreich.