Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Opmerking
Dit is niet de nieuwste versie van dit artikel. Zie de .NET 9-versie van dit artikel voor de huidige release.
Waarschuwing
Deze versie van ASP.NET Core wordt niet meer ondersteund. Zie het .NET- en .NET Core-ondersteuningsbeleid voor meer informatie. Zie de .NET 9-versie van dit artikel voor de huidige release.
Belangrijk
Deze informatie heeft betrekking op een pre-releaseproduct dat aanzienlijk kan worden gewijzigd voordat het commercieel wordt uitgebracht. Microsoft geeft geen garanties, uitdrukkelijk of impliciet, met betrekking tot de informatie die hier wordt verstrekt.
Zie de .NET 9-versie van dit artikel voor de huidige release.
Door Rick Anderson en Kirk Larkin
In dit artikel wordt laten zien hoe Cross-Origin Resource Sharing (CORS) is ingeschakeld in een ASP.NET Core-app.
Browserbeveiliging voorkomt dat een webpagina aanvragen indient naar een ander domein dan het domein dat de webpagina heeft geleverd. Deze beperking wordt het same-origin policy genoemd. Hetzelfde origin-beleid voorkomt dat een kwaadwillende site gevoelige gegevens van een andere site leest. Soms wilt u toestaan dat andere sites cross-origin-aanvragen indienen bij uw app. Zie het Mozilla CORS-artikel voor meer informatie.
Cross Origin Resource Sharing (CORS):
- Is een W3C-standaard waarmee een server hetzelfde origin-beleid kan versoepelen.
- Is geen beveiligingsfunctie, CORS maakt de beveiliging soepeler. Een API is niet veiliger door CORS toe te staan. Zie Hoe CORS werkt voor meer informatie.
- Hiermee staat u een server toe om bepaalde cross-origin-aanvragen expliciet toe te staan terwijl andere aanvragen worden geweigerd.
- Is veiliger en flexibeler dan eerdere technieken, zoals JSONP.
Voorbeeldcode bekijken of downloaden (hoe download je)
Dezelfde oorsprong
Twee URL's hebben dezelfde oorsprong als ze identieke schema's, hosts en poorten (RFC 6454) hebben.
Deze twee URL's hebben dezelfde oorsprong:
https://example.com/foo.html
https://example.com/bar.html
Deze URL's hebben verschillende oorsprongen dan de vorige twee URL's:
-
https://example.net
: Ander domein -
https://contoso.example.com/foo.html
: Ander subdomein -
http://example.com/foo.html
: Verschillend schema -
https://example.com:9000/foo.html
: Andere poort
CORS inschakelen
Er zijn drie manieren om CORS in te schakelen:
- In middleware met behulp van een benoemd beleid of standaardbeleid.
- Het gebruik van eindpuntroutering.
- Met het kenmerk [EnableCors] .
Het gebruik van het kenmerk [EnableCors] met een benoemd beleid biedt het beste beheer voor het beperken van eindpunten die CORS ondersteunen.
Waarschuwing
UseCors moet in de juiste volgorde worden aangeroepen. Zie Middleware-bestelling voor meer informatie. Moet bijvoorbeeld UseCors
worden aangeroepen voordat UseResponseCaching wanneer UseResponseCaching
wordt gebruikt.
Elke benadering wordt in de volgende secties beschreven.
CORS met benoemd beleid en middleware
CORS Middleware verwerkt cross-origin-aanvragen. Met de volgende code wordt een CORS-beleid toegepast op alle eindpunten van de app met de opgegeven oorsprongen:
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();
De voorgaande code:
- Hiermee stelt u de beleidsnaam in op
_myAllowSpecificOrigins
. De beleidsnaam is willekeurig. - Roept de UseCors extensiemethode aan en geeft het
_myAllowSpecificOrigins
CORS-beleid op.UseCors
voegt de CORS-middleware toe. De aanroep naarUseCors
moet worden geplaatst nadatUseRouting
, maar vóórUseAuthorization
. Zie Middleware-bestelling voor meer informatie. - Aanroepen AddCors met een lambda-expressie. De lambda neemt een CorsPolicyBuilder object.
Configuratieopties, zoals
WithOrigins
, worden verderop in dit artikel beschreven. - Hiermee schakelt u het
_myAllowSpecificOrigins
CORS-beleid in voor alle controllereindpunten. Zie eindpuntroutering om een CORS-beleid toe te passen op specifieke eindpunten. - Wanneer u Middleware voor antwoordcaching gebruikt, roept u UseCors eerder UseResponseCachingaan.
Met eindpuntroutering moet de CORS-middleware worden geconfigureerd voor uitvoering tussen de aanroepen naar UseRouting
en UseEndpoints
.
Met de AddCors methodeoproep worden CORS-services toegevoegd aan de servicecontainer van de app:
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();
Zie CORS-beleidsopties in dit document voor meer informatie.
De CorsPolicyBuilder methoden kunnen worden gekoppeld, zoals wordt weergegeven in de volgende code:
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();
Opmerking: de opgegeven URL mag geen afsluitende slash (/
) bevatten. Als de URL eindigt met /
, levert de vergelijking false
op en wordt er geen header geretourneerd.
Volgorde van UseCors en UseStaticFiles
UseStaticFiles
Normaal gesproken wordt het eerder UseCors
aangeroepen. Apps die JavaScript gebruiken om statische bestanden cross-site op te halen, moeten UseCors
aanroepen voordat ze UseStaticFiles
.
CORS met standaardbeleid en middleware
Met de volgende gemarkeerde code wordt het standaard CORS-beleid ingeschakeld:
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();
Met de voorgaande code wordt het standaard CORS-beleid toegepast op alle controllereindpunten.
Cors met eindpuntroutering inschakelen
Met eindpuntroutering kan CORS per eindpunt worden ingeschakeld met behulp van de RequireCors set extensiemethoden:
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();
In de voorgaande code:
-
app.UseCors
schakelt de CORS-middleware in. Omdat er geen standaardbeleid is geconfigureerd, maaktapp.UseCors()
alleen CORS niet mogelijk. - De
/echo
- en controle-eindpunten staan cross-origin-aanvragen toe met behulp van het opgegeven beleid. - De
/echo2
en Razor Pagina-eindpunten staan geen cross-origin-aanvragen toe omdat er geen standaardbeleid is opgegeven.
Het kenmerk [DisableCors] schakelt niet de CORS uit die is ingeschakeld door eindpuntroutering met RequireCors
.
Zie CORS testen met het kenmerk [EnableCors] en de RequireCors-methode voor instructies over het testen van code die vergelijkbaar is met de voorgaande.
CORS met kenmerken inschakelen
Het inschakelen van CORS met het kenmerk [EnableCors] en het toepassen van een benoemd beleid op alleen die eindpunten waarvoor CORS is vereist, biedt het beste beheer.
Het kenmerk [EnableCors] biedt een alternatief voor het wereldwijd toepassen van CORS. Met [EnableCors]
het kenmerk wordt CORS ingeschakeld voor geselecteerde eindpunten, in plaats van alle eindpunten:
-
[EnableCors]
hiermee geeft u het standaardbeleid. -
[EnableCors("{Policy String}")]
specificeert een benoemd beleid.
Het [EnableCors]
kenmerk kan worden toegepast op:
-
Razor Bladzijde
PageModel
- Controleur
- Controller-actiemethode
Verschillende beleidsregels kunnen worden toegepast op controllers, paginamodellen of actiemethoden met het [EnableCors]
kenmerk. Wanneer het [EnableCors]
kenmerk wordt toegepast op een controller, paginamodel of actiemethode en CORS is ingeschakeld in middleware, worden beide beleidsregels toegepast. Wij raden aan om beleidsregels niet te combineren. Gebruik de
[EnableCors]
kenmerk of middleware, niet beide in dezelfde app.
Met de volgende code wordt een ander beleid toegepast op elke methode:
[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(),
};
}
}
Met de volgende code worden twee CORS-beleidsregels gemaakt:
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();
Voor de beste controle over het beperken van CORS-aanvragen:
- Gebruik
[EnableCors("MyPolicy")]
met een genaamd beleid. - Definieer geen standaardbeleid.
- Gebruik geen eindpuntroutering.
De code in de volgende sectie voldoet aan de voorgaande lijst.
CORS uitschakelen
Het kenmerk [DisableCors] schakelt CORS die is ingeschakeld door eindpuntrouteringniet uit.
De volgende code definieert het CORS-beleid "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();
Met de volgende code wordt CORS uitgeschakeld voor de GetValues2
actie:
[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();
}
De voorgaande code:
- CORS wordt niet ingeschakeld met eindpuntroutering.
- Definieert geen standaard CORS-beleid.
- Gebruikt [EnableCors("MyPolicy")] om het
"MyPolicy"
CORS-beleid voor de controller in te schakelen. - Hiermee schakelt u CORS voor de
GetValues2
methode uit.
Zie CORS testen voor instructies over het testen van de voorgaande code.
CORS-beleidsopties
In deze sectie worden de verschillende opties beschreven die kunnen worden ingesteld in een CORS-beleid:
- De toegestane oorsprongen instellen
- De toegestane HTTP-methoden instellen
- De toegestane aanvraagheaders instellen
- De weergegeven antwoordheaders instellen
- Inloggegevens in cross-origin-aanvragen
- De verlooptijd van de voorbereidende fase instellen
AddPolicy wordt ingeroepen in Program.cs
. Voor sommige opties kan het nuttig zijn om eerst de sectie Hoe CORS werkt te lezen.
De toegestane oorsprongen instellen
AllowAnyOrigin: Hiermee staat u CORS-aanvragen van alle oorsprongen toe met elk schema (http
of https
).
AllowAnyOrigin
is onveilig omdat elke website cross-origin aanvragen kan indienen bij de app.
Opmerking
Het opgeven van AllowAnyOrigin
en AllowCredentials
is een onveilige configuratie en leidt tot cross-site request-vervalsing. De CORS-service retourneert een ongeldig CORS-antwoord wanneer een app is geconfigureerd met beide methoden.
AllowAnyOrigin
beïnvloedt preflight-aanvragen en de Access-Control-Allow-Origin
-koptekst. Zie de sectie Voorbereidende aanvragen voor meer informatie.
SetIsOriginAllowedToAllowWildcardSubdomains: Hiermee stelt u de IsOriginAllowed eigenschap van het beleid in als een functie waarmee origins overeenkomen met een geconfigureerd wildcarddomein bij het evalueren of de oorsprong is toegestaan.
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();
De toegestane HTTP-methoden instellen
- Hiermee staat u elke HTTP-methode toe:
- Beïnvloedt voorbereidende aanvragen en de
Access-Control-Allow-Methods
-header. Zie de sectie Voorbereidende aanvragen voor meer informatie.
De toegestane aanvraagheaders instellen
Als u wilt toestaan dat specifieke headers worden verzonden in een CORS-aanvraag, genaamd headers van auteursaanvragen, roept WithHeaders u de toegestane headers aan en geeft u de toegestane headers op:
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();
Als u alle verzoekheaders van de auteur wilt toestaan, roept u AllowAnyHeader aan.
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
beïnvloedt preflight-aanvragen en de Access-Control-Request-Headers-header. Zie de sectie Voorbereidende aanvragen voor meer informatie.
Een CORS Middleware-beleid matcht met specifieke headers gespecificeerd door WithHeaders
alleen wanneer de headers in Access-Control-Request-Headers
exact overeenkomen met de headers die zijn gespecificeerd in WithHeaders
.
Denk bijvoorbeeld aan een app die als volgt is geconfigureerd:
app.UseCors(policy => policy.WithHeaders(HeaderNames.CacheControl));
CORS Middleware weigert een voorafgaande aanvraag met de volgende aanvraagheader omdat Content-Language
(HeaderNames.ContentLanguage) niet wordt vermeld in WithHeaders
:
Access-Control-Request-Headers: Cache-Control, Content-Language
De app retourneert een 200 OK-antwoord , maar stuurt de CORS-headers niet terug. Daarom probeert de browser de cross-origin-aanvraag niet uit te voeren.
De weergegeven antwoordheaders instellen
Standaard worden in de browser niet alle antwoordheaders voor de app weergegeven. Zie W3C Cross-Origin Resource Sharing (Terminologie): Simple Response Header voor meer informatie.
De antwoordheaders die standaard beschikbaar zijn, zijn:
Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma
De CORS-specificatie roept deze headers eenvoudige antwoordheaders aan. Als u andere headers beschikbaar wilt maken voor de app, roept u het volgende WithExposedHeadersaan:
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();
Inloggegevens in cross-origin-aanvragen
Referenties vereisen speciale verwerking in een CORS-aanvraag. Standaard verzendt de browser geen inloggegevens met een cross-origin-aanvraag. Inloggegevens omvatten cookies en HTTP-authenticatieschema's. Om referenties met een cross-origin verzoek mee te sturen, moet de client XMLHttpRequest.withCredentials
instellen op true
.
Gebruik rechtstreeks XMLHttpRequest
:
var xhr = new XMLHttpRequest();
xhr.open('get', 'https://www.example.com/api/test');
xhr.withCredentials = true;
JQuery gebruiken:
$.ajax({
type: 'get',
url: 'https://www.example.com/api/test',
xhrFields: {
withCredentials: true
}
});
fetch('https://www.example.com/api/test', {
credentials: 'include'
});
De server moet de inloggegevens toestaan. Als u referenties voor meerdere oorsprongen wilt toestaan, roept u AllowCredentials op.
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();
Het HTTP-antwoord bevat een Access-Control-Allow-Credentials
header, waarmee de browser aangeeft dat de server referenties toestaat voor een cross-origin-aanvraag.
Als de browser referenties verzendt, maar het antwoord geen geldige Access-Control-Allow-Credentials
header bevat, geeft de browser het antwoord niet beschikbaar aan de app en mislukt de cross-origin-aanvraag.
Het toestaan van cross-origin credentials is een beveiligingsrisico. Een website in een ander domein kan de referenties van een aangemelde gebruiker namens de gebruiker verzenden naar de app zonder dat de gebruiker dit weet.
De CORS-specificatie geeft ook aan dat het instellen van origins op "*"
(alle origins) ongeldig is als de Access-Control-Allow-Credentials
header aanwezig is.
Preflight-verzoeken
Voor sommige CORS-aanvragen verzendt de browser een extra OPTIONS-aanvraag voordat de werkelijke aanvraag wordt ingediend. Deze aanvraag wordt een voorbereidende aanvraag genoemd. De browser kan de voorbereidende aanvraag overslaan als aan alle volgende voorwaarden wordt voldaan:
- De aanvraagmethode is GET, HEAD of POST.
- De app stelt geen andere aanvraagheaders in dan
Accept
,Accept-Language
,Content-Language
,Content-Type
ofLast-Event-ID
. - De
Content-Type
header, indien ingesteld, heeft een van de volgende waarden:application/x-www-form-urlencoded
multipart/form-data
text/plain
De regel voor aanvraagheaders die zijn ingesteld voor de clientaanvraag is van toepassing op headers die door de app worden ingesteld door setRequestHeader
aan te roepen op het XMLHttpRequest
-object. De CORS-specificatie noemt deze headers auteursaanvraagheaders. De regel is niet van toepassing op headers die de browser kan instellen, zoals User-Agent
, Host
of Content-Length
.
Opmerking
Dit artikel bevat URL's die zijn gemaakt door de voorbeeldcode te implementeren op twee Azure-websites en https://cors3.azurewebsites.net
https://cors.azurewebsites.net
.
Hier volgt een voorbeeld van een antwoord dat lijkt op het preflight-verzoek dat is gedaan via de knop [Put test] in de Test CORS sectie van dit document.
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
Het preflight-verzoek gebruikt de HTTP OPTIONS methode. Het kan de volgende headers bevatten:
- Access-Control-Request-Method: de HTTP-methode die wordt gebruikt voor de werkelijke aanvraag.
-
Access-Control-Request-Headers: een lijst met aanvraagheaders die door de app worden ingesteld voor de werkelijke aanvraag. Zoals eerder vermeld, bevat dit geen headers die door de browser worden ingesteld, zoals
User-Agent
.
Als de voorbereidende aanvraag wordt geweigerd, retourneert de app een 200 OK
antwoord, maar de CORS-headers worden niet ingesteld. Daarom probeert de browser de cross-origin-aanvraag niet uit te voeren. Voor een voorbeeld van een geweigerde voorbereidende aanvraag, zie de sectie Test CORS van dit document.
Met de F12-hulpprogramma's wordt in de console-app een fout weergegeven die vergelijkbaar is met een van de volgende, afhankelijk van de browser:
- Firefox: Cross-Origin-aanvraag geblokkeerd: de Same-Origin Policy staat het lezen van de externe resource op
https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5
niet toe. (Reden: CORS-aanvraag is niet geslaagd). Meer informatie - Op basis van Chromium: Toegang tot het ophalen van 'https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5' vanaf oorsprong 'https://cors3.azurewebsites.net' is geblokkeerd door CORS-beleid: Reactie op preflight-verzoek voldoet niet aan de toegangscontrole: Er is geen 'Access-Control-Allow-Origin'-header aanwezig op de opgevraagde resource. Als een ondoorzichtig antwoord aan uw behoeften voldoet, stelt u de modus van de aanvraag in op 'no-cors' om de resource op te halen waarvoor CORS is uitgeschakeld.
Als u specifieke headers wilt toestaan, roept u het volgende aan 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();
Als u alle verzoekheaders van de auteur wilt toestaan, roept u AllowAnyHeader aan.
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();
Browsers zijn niet consistent in de wijze waarop ze zijn ingesteld Access-Control-Request-Headers
. Als een van beide:
- Kopteksten zijn ingesteld op iets anders dan
"*"
-
AllowAnyHeader wordt aangeroepen: neem ten minste
Accept
,Content-Type
enOrigin
plus eventuele aangepaste headers op die u wilt ondersteunen.
Code voor automatische preflightaanvraag
Wanneer het CORS-beleid wordt toegepast, ofwel:
- Wereldwijd door
app.UseCors
inProgram.cs
te bellen. - Gebruikmakend van het
[EnableCors]
kenmerk.
ASP.NET Core reageert op de preflight-OPTIES-aanvraag.
In de sectie CORS testen van dit document ziet u dit gedrag.
Kenmerk [HttpOptions] voor preflightverzoeken
Wanneer CORS is ingeschakeld met het juiste beleid, reageert ASP.NET Core in het algemeen automatisch op CORS-voorbereidende aanvragen.
De volgende code maakt gebruik van het kenmerk [HttpOptions] voor het maken van eindpunten voor OPTIONS-aanvragen:
[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);
}
Zie CORS testen met het kenmerk [EnableCors] en de RequireCors-methode voor instructies over het testen van de voorgaande code.
De verlooptijd van de voorbereidende fase instellen
De Access-Control-Max-Age
header geeft aan hoe lang het antwoord op het preflight-verzoek in de cache kan worden opgeslagen. Als u deze header wilt instellen, roept u het volgende SetPreflightMaxAgeaan:
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();
CORS inschakelen op een eindpunt
Hoe CORS werkt
In deze sectie wordt beschreven wat er gebeurt in een CORS-aanvraag op het niveau van de HTTP-berichten.
- CORS is geen beveiligingsfunctie. CORS is een W3C-standaard waarmee een server hetzelfde origin-beleid kan versoepelen.
- Een kwaadwillende actor kan bijvoorbeeld XSS (Cross-Site Scripting) gebruiken op uw site en een cross-site-aanvraag uitvoeren op hun CORS-site om informatie te stelen.
- Een API is niet veiliger door CORS toe te staan.
- Het is aan de client (browser) om CORS af te dwingen. De server voert de aanvraag uit en retourneert het antwoord, het is de client die een fout retourneert en het antwoord blokkeert. Met een van de volgende hulpprogramma's wordt bijvoorbeeld het serverantwoord weergegeven:
- Speelman
- .NET HttpClient
- Een webbrowser door de URL in de adresbalk in te voeren.
- Het is aan de client (browser) om CORS af te dwingen. De server voert de aanvraag uit en retourneert het antwoord, het is de client die een fout retourneert en het antwoord blokkeert. Met een van de volgende hulpprogramma's wordt bijvoorbeeld het serverantwoord weergegeven:
- Het is een manier voor een server om browsers toe te staan een cross-origin XHR - of Fetch API-aanvraag uit te voeren die anders verboden zou zijn.
- Browsers zonder CORS kunnen geen cross-origin-aanvragen uitvoeren. Vóór CORS werd JSONP gebruikt om deze beperking te omzeilen. JSONP gebruikt geen XHR, maar gebruikt de
<script>
tag om het antwoord te ontvangen. Scripts mogen cross-origin worden geladen.
- Browsers zonder CORS kunnen geen cross-origin-aanvragen uitvoeren. Vóór CORS werd JSONP gebruikt om deze beperking te omzeilen. JSONP gebruikt geen XHR, maar gebruikt de
De CORS-specificatie heeft verschillende nieuwe HTTP-headers geïntroduceerd die cross-origin-aanvragen mogelijk maken. Als een browser CORS ondersteunt, worden deze headers automatisch ingesteld voor cross-origin-aanvragen. Aangepaste JavaScript-code is niet vereist om CORS in te schakelen.
Dit is een voorbeeld van een cross-origin-aanvraag van de waardentest-knop naar https://cors1.azurewebsites.net/api/values
. De Origin
koptekst:
- Geeft het domein van de site die het verzoek indient.
- Is vereist en moet afwijken van de host.
Algemene headers
Request URL: https://cors1.azurewebsites.net/api/values
Request Method: GET
Status Code: 200 OK
Antwoordheaders
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
Verzoekheaders
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
aanvragen stelt de server de header AntwoordheadersAccess-Control-Allow-Origin: {allowed origin}
in het antwoord in. In de voorbeeldcode bevat de Delete [EnableCors]
knopaanvraag OPTIONS
bijvoorbeeld de volgende headers:
Algemene headers
Request URL: https://cors3.azurewebsites.net/api/TodoItems2/MyDelete2/5
Request Method: OPTIONS
Status Code: 204 No Content
Antwoordheaders
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
Verzoekheaders
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 de voorgaande antwoordheaders stelt de server in het antwoord de header Access-Control-Allow-Origin in. De https://cors1.azurewebsites.net
waarde van deze header komt overeen met de Origin
header van de aanvraag.
Als AllowAnyOrigin wordt aangeroepen, wordt de Access-Control-Allow-Origin: *
, de jokertekenwaarde, geretourneerd.
AllowAnyOrigin
staat elke oorsprong toe.
Als het antwoord de header niet bevat Access-Control-Allow-Origin
, mislukt de cross-origin-aanvraag. De browser staat de aanvraag met name niet toe. Zelfs als de server een geslaagd antwoord retourneert, maakt de browser het antwoord niet beschikbaar voor de client-app.
HTTP-omleiding naar HTTPS veroorzaakt ERR_INVALID_REDIRECT op de preflight CORS-verzoek
Aanvragen naar een eindpunt met HTTP die door UseHttpsRedirection worden omgeleid naar HTTPS, mislukken met ERR_INVALID_REDIRECT on the CORS preflight request
.
API-projecten kunnen HTTP-aanvragen weigeren in plaats van te gebruiken UseHttpsRedirection
om aanvragen om te leiden naar HTTPS.
CORS in IIS
Bij de implementatie in IIS moet CORS worden uitgevoerd vóór Windows-verificatie als de server niet is geconfigureerd om anonieme toegang toe te staan. Ter ondersteuning van dit scenario moet de IIS CORS-module worden geïnstalleerd en geconfigureerd voor de app.
CORS testen
Het voorbeelddownload bevat code om CORS te testen. Zie hoe ukunt downloaden. Het voorbeeld is een API-project met Razor Pages toegevoegd:
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();
Waarschuwing
WithOrigins("https://localhost:<port>");
mag alleen worden gebruikt voor het testen van een voorbeeld-app die vergelijkbaar is met de voorbeeldcode voor het downloaden.
Opmerking
Als u in Visual Studio werkt launchSettings.json
of C#-foutopsporingsinstellingen in VS Code configureert en IIS Express gebruikt om lokaal fouten op te sporen, moet u ervoor zorgen dat u IIS Express hebt geconfigureerd voor "anonymousAuthentication": true
. Wanneer "anonymousAuthentication"
false
is, ziet de host van de ASP.NET Core-webomgeving geen preflight-verzoeken. Met name als u gebruikmaakt van NTLM-verificatie ("windowsAuthentication": true
), is de eerste stap van het NTLM-vraag-antwoord proces het versturen van een 401-uitdaging naar de webbrowser, waardoor het lastig kan zijn om te controleren of uw preflight-aanroep correct is geconfigureerd.
ValuesController
Hieronder vindt u de eindpunten voor het testen:
[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 wordt geleverd door het Rick.Docs.Samples.RouteInfo NuGet-pakket en toont routegegevens.
Test de voorgaande voorbeeldcode met behulp van een van de volgende methoden:
- Voer het voorbeeld uit met
dotnet run
behulp van de standaard-URL vanhttps://localhost:5001
. - Voer het voorbeeld uit vanuit Visual Studio met de poort ingesteld op 44398 voor een URL van
https://localhost:44398
.
Een browser gebruiken met de F12-hulpprogramma's:
Selecteer de knop Waarden en controleer de kopteksten op het tabblad Netwerk .
Selecteer de PUT-test knop. Zie WeergaveOPTIES-aanvragen voor instructies over het weergeven van de OPTIONS-aanvraag. De PUT-test maakt twee aanvragen, een OPTIONS preflight-aanvraag en een PUT-aanvraag.
Selecteer de
GetValues2 [DisableCors]
knop om een mislukte CORS-aanvraag te activeren. Zoals vermeld in het document, retourneert het antwoord 200 succes, maar wordt het CORS-verzoek niet gedaan. Selecteer het tabblad Console om de CORS-fout weer te geven. Afhankelijk van de browser wordt een fout weergegeven die lijkt op het volgende:Toegang voor het ophalen van
'https://cors1.azurewebsites.net/api/values/GetValues2'
vanaf oorsprong'https://cors3.azurewebsites.net'
is geblokkeerd door het CORS-beleid: Er is geen 'Access-Control-Allow-Origin' header aanwezig op de aangevraagde resource. Als een ondoorzichtig antwoord aan uw behoeften voldoet, stelt u de modus van de aanvraag in op 'no-cors' om de resource op te halen waarvoor CORS is uitgeschakeld.
CORS-eindpunten kunnen worden getest met een hulpprogramma, zoals curl of Fiddler. Wanneer u een hulpprogramma gebruikt, moet de oorsprong van de aanvraag die is opgegeven door de Origin
header verschillen van de host die de aanvraag ontvangt. Als de aanvraag niet cross-origin is op basis van de waarde van de Origin
header:
- Cors Middleware is niet nodig om de aanvraag te verwerken.
- CORS-headers worden niet geretourneerd in het antwoord.
Met de volgende opdracht curl
wordt een OPTIONS-aanvraag met informatie verzonden:
curl -X OPTIONS https://cors3.azurewebsites.net/api/TodoItems2/5 -i
CORS testen met het kenmerk [EnableCors] en de RequireCors-methode
Houd rekening met de volgende code die eindpuntroutering gebruikt om CORS per eindpunt in te schakelen met behulp van 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();
Merk op dat alleen het /echo
eindpunt het gebruik van RequireCors
toestaat om cross-origin aanvragen mogelijk te maken volgens het opgegeven beleid. De onderstaande controllers schakelen CORS in met behulp van het kenmerk [EnableCors].
TodoItems1Controller
Hieronder vindt u eindpunten voor het testen:
[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);
}
De knoppen Delete [EnableCors] en GET [EnableCors] slagen, omdat de eindpunten [EnableCors]
hebben voor preflight-aanvragen en daarop reageren. De andere eindpunten mislukken. De get-knop mislukt, omdat javaScript het volgende verzendt:
headers: {
"Content-Type": "x-custom-header"
},
Het volgende TodoItems2Controller
biedt vergelijkbare eindpunten, maar bevat expliciete code om te reageren op OPTIONS-aanvragen:
[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);
}
De voorgaande code kan worden getest door het voorbeeld in Azure te implementeren. Selecteer Preflight in de vervolgkeuzelijst Controller en stel controller in. Alle CORS-aanroepen naar de TodoItems2Controller
eindpunten zijn geslaagd.
Aanvullende bronnen
Door Rick Anderson en Kirk Larkin
In dit artikel wordt beschreven hoe u CORS inschakelt in een ASP.NET Core-app.
Browserbeveiliging voorkomt dat een webpagina aanvragen indient naar een ander domein dan het domein dat de webpagina heeft geleverd. Deze beperking wordt het same-origin policy genoemd. Hetzelfde origin-beleid voorkomt dat een kwaadwillende site gevoelige gegevens van een andere site leest. Soms wilt u toestaan dat andere sites cross-origin-aanvragen indienen bij uw app. Zie het Mozilla CORS-artikel voor meer informatie.
Cross Origin Resource Sharing (CORS):
- Is een W3C-standaard waarmee een server hetzelfde origin-beleid kan versoepelen.
- Is geen beveiligingsfunctie, CORS maakt de beveiliging soepeler. Een API is niet veiliger door CORS toe te staan. Zie Hoe CORS werkt voor meer informatie.
- Hiermee staat u een server toe om bepaalde cross-origin-aanvragen expliciet toe te staan terwijl andere aanvragen worden geweigerd.
- Is veiliger en flexibeler dan eerdere technieken, zoals JSONP.
Voorbeeldcode bekijken of downloaden (hoe download je)
Dezelfde oorsprong
Twee URL's hebben dezelfde oorsprong als ze identieke schema's, hosts en poorten (RFC 6454) hebben.
Deze twee URL's hebben dezelfde oorsprong:
https://example.com/foo.html
https://example.com/bar.html
Deze URL's hebben verschillende oorsprongen dan de vorige twee URL's:
-
https://example.net
: Ander domein -
https://www.example.com/foo.html
: Ander subdomein -
http://example.com/foo.html
: Verschillend schema -
https://example.com:9000/foo.html
: Andere poort
CORS inschakelen
Er zijn drie manieren om CORS in te schakelen:
- In middleware met behulp van een benoemd beleid of standaardbeleid.
- Het gebruik van eindpuntroutering.
- Met het kenmerk [EnableCors] .
Het gebruik van het kenmerk [EnableCors] met een benoemd beleid biedt het beste beheer voor het beperken van eindpunten die CORS ondersteunen.
Waarschuwing
UseCors moet in de juiste volgorde worden aangeroepen. Zie Middleware-bestelling voor meer informatie. Moet bijvoorbeeld UseCors
worden aangeroepen voordat UseResponseCaching wanneer UseResponseCaching
wordt gebruikt.
Elke benadering wordt in de volgende secties beschreven.
CORS met benoemd beleid en middleware
CORS Middleware verwerkt cross-origin-aanvragen. Met de volgende code wordt een CORS-beleid toegepast op alle eindpunten van de app met de opgegeven oorsprongen:
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();
De voorgaande code:
- Hiermee stelt u de beleidsnaam in op
_myAllowSpecificOrigins
. De beleidsnaam is willekeurig. - Roept de UseCors extensiemethode aan en geeft het
_myAllowSpecificOrigins
CORS-beleid op.UseCors
voegt de CORS-middleware toe. De aanroep naarUseCors
moet worden geplaatst nadatUseRouting
, maar vóórUseAuthorization
. Zie Middleware-bestelling voor meer informatie. - Aanroepen AddCors met een lambda-expressie. De lambda neemt een CorsPolicyBuilder object.
Configuratieopties, zoals
WithOrigins
, worden verderop in dit artikel beschreven. - Hiermee schakelt u het
_myAllowSpecificOrigins
CORS-beleid in voor alle controllereindpunten. Zie eindpuntroutering om een CORS-beleid toe te passen op specifieke eindpunten. - Wanneer u Middleware voor antwoordcaching gebruikt, roept u UseCors eerder UseResponseCachingaan.
Met eindpuntroutering moet de CORS-middleware worden geconfigureerd voor uitvoering tussen de aanroepen naar UseRouting
en UseEndpoints
.
Met de AddCors methodeoproep worden CORS-services toegevoegd aan de servicecontainer van de app:
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();
Zie CORS-beleidsopties in dit document voor meer informatie.
De CorsPolicyBuilder methoden kunnen worden gekoppeld, zoals wordt weergegeven in de volgende code:
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();
Opmerking: de opgegeven URL mag geen afsluitende slash (/
) bevatten. Als de URL eindigt met /
, levert de vergelijking false
op en wordt er geen header geretourneerd.
Waarschuwing
UseCors
moet na UseRouting
en vóór UseAuthorization
worden geplaatst. Dit is om ervoor te zorgen dat CORS-headers worden opgenomen in het antwoord voor geautoriseerde en niet-geautoriseerde aanroepen.
Volgorde van UseCors en UseStaticFiles
UseStaticFiles
Normaal gesproken wordt het eerder UseCors
aangeroepen. Apps die JavaScript gebruiken om statische bestanden cross-site op te halen, moeten UseCors
aanroepen voordat ze UseStaticFiles
.
CORS met standaardbeleid en middleware
Met de volgende gemarkeerde code wordt het standaard CORS-beleid ingeschakeld:
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();
Met de voorgaande code wordt het standaard CORS-beleid toegepast op alle controllereindpunten.
Cors met eindpuntroutering inschakelen
Met eindpuntroutering kan CORS per eindpunt worden ingeschakeld met behulp van de RequireCors set extensiemethoden:
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();
In de voorgaande code:
-
app.UseCors
schakelt de CORS-middleware in. Omdat er geen standaardbeleid is geconfigureerd, maaktapp.UseCors()
alleen CORS niet mogelijk. - De
/echo
- en controle-eindpunten staan cross-origin-aanvragen toe met behulp van het opgegeven beleid. - De
/echo2
en Razor Pagina-eindpunten staan geen cross-origin-aanvragen toe omdat er geen standaardbeleid is opgegeven.
Het kenmerk [DisableCors] schakelt niet de CORS uit die is ingeschakeld door eindpuntroutering met RequireCors
.
In .NET 7 moet het [EnableCors]
kenmerk een parameter doorgeven, anders wordt er een ASP0023 waarschuwing gegenereerd vanwege een onduidelijke overeenkomst op de route. De waarschuwing wordt niet gegenereerd ASP0023
door .NET 8 of hoger.
[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);
}
Zie CORS testen met het kenmerk [EnableCors] en de RequireCors-methode voor instructies over het testen van code die vergelijkbaar is met de voorgaande.
CORS met kenmerken inschakelen
Het inschakelen van CORS met het kenmerk [EnableCors] en het toepassen van een benoemd beleid op alleen die eindpunten waarvoor CORS is vereist, biedt het beste beheer.
Het kenmerk [EnableCors] biedt een alternatief voor het wereldwijd toepassen van CORS. Met [EnableCors]
het kenmerk wordt CORS ingeschakeld voor geselecteerde eindpunten, in plaats van alle eindpunten:
-
[EnableCors]
hiermee geeft u het standaardbeleid. -
[EnableCors("{Policy String}")]
specificeert een benoemd beleid.
Het [EnableCors]
kenmerk kan worden toegepast op:
-
Razor Bladzijde
PageModel
- Controleur
- Controller-actiemethode
Verschillende beleidsregels kunnen worden toegepast op controllers, paginamodellen of actiemethoden met het [EnableCors]
kenmerk. Wanneer het [EnableCors]
kenmerk wordt toegepast op een controller, paginamodel of actiemethode en CORS is ingeschakeld in middleware, worden beide beleidsregels toegepast. Wij raden aan om beleidsregels niet te combineren. Gebruik de
[EnableCors]
kenmerk of middleware, niet beide in dezelfde app.
Met de volgende code wordt een ander beleid toegepast op elke methode:
[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(),
};
}
}
Met de volgende code worden twee CORS-beleidsregels gemaakt:
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();
Voor de beste controle over het beperken van CORS-aanvragen:
- Gebruik
[EnableCors("MyPolicy")]
met een genaamd beleid. - Definieer geen standaardbeleid.
- Gebruik geen eindpuntroutering.
De code in de volgende sectie voldoet aan de voorgaande lijst.
CORS uitschakelen
Het kenmerk [DisableCors] schakelt CORS die is ingeschakeld door eindpuntrouteringniet uit.
De volgende code definieert het CORS-beleid "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();
Met de volgende code wordt CORS uitgeschakeld voor de GetValues2
actie:
[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();
}
De voorgaande code:
- CORS wordt niet ingeschakeld met eindpuntroutering.
- Definieert geen standaard CORS-beleid.
- Gebruikt [EnableCors("MyPolicy")] om het
"MyPolicy"
CORS-beleid voor de controller in te schakelen. - Hiermee schakelt u CORS voor de
GetValues2
methode uit.
Zie CORS testen voor instructies over het testen van de voorgaande code.
CORS-beleidsopties
In deze sectie worden de verschillende opties beschreven die kunnen worden ingesteld in een CORS-beleid:
- De toegestane oorsprongen instellen
- De toegestane HTTP-methoden instellen
- De toegestane aanvraagheaders instellen
- De weergegeven antwoordheaders instellen
- Inloggegevens in cross-origin-aanvragen
- De verlooptijd van de voorbereidende fase instellen
AddPolicy wordt ingeroepen in Program.cs
. Voor sommige opties kan het nuttig zijn om eerst de sectie Hoe CORS werkt te lezen.
De toegestane oorsprongen instellen
AllowAnyOrigin: Hiermee staat u CORS-aanvragen van alle oorsprongen toe met elk schema (http
of https
).
AllowAnyOrigin
is onveilig omdat elke website cross-origin aanvragen kan indienen bij de app.
Opmerking
Het opgeven van AllowAnyOrigin
en AllowCredentials
is een onveilige configuratie en leidt tot cross-site request-vervalsing. De CORS-service retourneert een ongeldig CORS-antwoord wanneer een app is geconfigureerd met beide methoden.
AllowAnyOrigin
beïnvloedt preflight-aanvragen en de Access-Control-Allow-Origin
-koptekst. Zie de sectie Voorbereidende aanvragen voor meer informatie.
SetIsOriginAllowedToAllowWildcardSubdomains: Hiermee stelt u de IsOriginAllowed eigenschap van het beleid in als een functie waarmee origins overeenkomen met een geconfigureerd wildcarddomein bij het evalueren of de oorsprong is toegestaan.
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();
De toegestane HTTP-methoden instellen
- Hiermee staat u elke HTTP-methode toe:
- Beïnvloedt voorbereidende aanvragen en de
Access-Control-Allow-Methods
-header. Zie de sectie Voorbereidende aanvragen voor meer informatie.
De toegestane aanvraagheaders instellen
Als u wilt toestaan dat specifieke headers worden verzonden in een CORS-aanvraag, genaamd headers van auteursaanvragen, roept WithHeaders u de toegestane headers aan en geeft u de toegestane headers op:
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();
Als u alle auteursaanvraagheaders wilt toestaan, roept u het volgende AllowAnyHeaderaan:
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
beïnvloedt preflight-aanvragen en de Access-Control-Request-Headers-header. Zie de sectie Voorbereidende aanvragen voor meer informatie.
Een CORS Middleware-beleid matcht met specifieke headers gespecificeerd door WithHeaders
alleen wanneer de headers in Access-Control-Request-Headers
exact overeenkomen met de headers die zijn gespecificeerd in WithHeaders
.
Denk bijvoorbeeld aan een app die als volgt is geconfigureerd:
app.UseCors(policy => policy.WithHeaders(HeaderNames.CacheControl));
CORS Middleware weigert een voorafgaande aanvraag met de volgende aanvraagheader omdat Content-Language
(HeaderNames.ContentLanguage) niet wordt vermeld in WithHeaders
:
Access-Control-Request-Headers: Cache-Control, Content-Language
De app retourneert een 200 OK-antwoord , maar stuurt de CORS-headers niet terug. Daarom probeert de browser de cross-origin-aanvraag niet uit te voeren.
De weergegeven antwoordheaders instellen
Standaard worden in de browser niet alle antwoordheaders voor de app weergegeven. Zie W3C Cross-Origin Resource Sharing (Terminologie): Simple Response Header voor meer informatie.
De antwoordheaders die standaard beschikbaar zijn, zijn:
Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma
De CORS-specificatie roept deze headers eenvoudige antwoordheaders aan. Als u andere headers beschikbaar wilt maken voor de app, roept u het volgende WithExposedHeadersaan:
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();
Inloggegevens in cross-origin-aanvragen
Referenties vereisen speciale verwerking in een CORS-aanvraag. Standaard verzendt de browser geen inloggegevens met een cross-origin-aanvraag. Inloggegevens omvatten cookies en HTTP-authenticatieschema's. Om referenties met een cross-origin verzoek mee te sturen, moet de client XMLHttpRequest.withCredentials
instellen op true
.
Gebruik rechtstreeks XMLHttpRequest
:
var xhr = new XMLHttpRequest();
xhr.open('get', 'https://www.example.com/api/test');
xhr.withCredentials = true;
JQuery gebruiken:
$.ajax({
type: 'get',
url: 'https://www.example.com/api/test',
xhrFields: {
withCredentials: true
}
});
fetch('https://www.example.com/api/test', {
credentials: 'include'
});
De server moet de inloggegevens toestaan. Als u referenties voor meerdere oorsprongen wilt toestaan, roept u AllowCredentials op.
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();
Het HTTP-antwoord bevat een Access-Control-Allow-Credentials
header, waarmee de browser aangeeft dat de server referenties toestaat voor een cross-origin-aanvraag.
Als de browser referenties verzendt, maar het antwoord geen geldige Access-Control-Allow-Credentials
header bevat, geeft de browser het antwoord niet beschikbaar aan de app en mislukt de cross-origin-aanvraag.
Het toestaan van cross-origin credentials is een beveiligingsrisico. Een website in een ander domein kan de referenties van een aangemelde gebruiker namens de gebruiker verzenden naar de app zonder dat de gebruiker dit weet.
De CORS-specificatie geeft ook aan dat het instellen van origins op "*"
(alle origins) ongeldig is als de Access-Control-Allow-Credentials
header aanwezig is.
Preflight-verzoeken
Voor sommige CORS-aanvragen verzendt de browser een extra OPTIONS-aanvraag voordat de werkelijke aanvraag wordt ingediend. Deze aanvraag wordt een voorbereidende aanvraag genoemd. De browser kan de voorbereidende aanvraag overslaan als aan alle volgende voorwaarden wordt voldaan:
- De aanvraagmethode is GET, HEAD of POST.
- De app stelt geen andere aanvraagheaders in dan
Accept
,Accept-Language
,Content-Language
,Content-Type
ofLast-Event-ID
. - De
Content-Type
header, indien ingesteld, heeft een van de volgende waarden:application/x-www-form-urlencoded
multipart/form-data
text/plain
De regel voor aanvraagheaders die zijn ingesteld voor de clientaanvraag is van toepassing op headers die door de app worden ingesteld door setRequestHeader
aan te roepen op het XMLHttpRequest
-object. De CORS-specificatie noemt deze headers auteursaanvraagheaders. De regel is niet van toepassing op headers die de browser kan instellen, zoals User-Agent
, Host
of Content-Length
.
Hier volgt een voorbeeld van een antwoord dat lijkt op het preflight-verzoek dat is gedaan via de knop [Put test] in de Test CORS sectie van dit document.
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
Het preflight-verzoek gebruikt de HTTP OPTIONS methode. Het kan de volgende headers bevatten:
- Access-Control-Request-Method: de HTTP-methode die wordt gebruikt voor de werkelijke aanvraag.
-
Access-Control-Request-Headers: een lijst met aanvraagheaders die door de app worden ingesteld voor de werkelijke aanvraag. Zoals eerder vermeld, bevat dit geen headers die door de browser worden ingesteld, zoals
User-Agent
. - Access-Control-Allow-Methods
Als de voorbereidende aanvraag wordt geweigerd, retourneert de app een 200 OK
antwoord, maar de CORS-headers worden niet ingesteld. Daarom probeert de browser de cross-origin-aanvraag niet uit te voeren. Voor een voorbeeld van een geweigerde voorbereidende aanvraag, zie de sectie Test CORS van dit document.
Met de F12-hulpprogramma's wordt in de console-app een fout weergegeven die vergelijkbaar is met een van de volgende, afhankelijk van de browser:
- Firefox: Cross-Origin-aanvraag geblokkeerd: de Same-Origin Policy staat het lezen van de externe resource op
https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5
niet toe. (Reden: CORS-aanvraag is niet geslaagd). Meer informatie - Op basis van Chromium: Toegang tot het ophalen van 'https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5' vanaf oorsprong 'https://cors3.azurewebsites.net' is geblokkeerd door CORS-beleid: Reactie op preflight-verzoek voldoet niet aan de toegangscontrole: Er is geen 'Access-Control-Allow-Origin'-header aanwezig op de opgevraagde resource. Als een ondoorzichtig antwoord aan uw behoeften voldoet, stelt u de modus van de aanvraag in op 'no-cors' om de resource op te halen waarvoor CORS is uitgeschakeld.
Als u specifieke headers wilt toestaan, roept u het volgende aan 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();
Als u alle auteursaanvraagheaders wilt toestaan, roept u het volgende AllowAnyHeaderaan:
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();
Browsers zijn niet consistent in de wijze waarop ze zijn ingesteld Access-Control-Request-Headers
. Als een van beide:
- Kopteksten zijn ingesteld op iets anders dan
"*"
-
AllowAnyHeader wordt aangeroepen: neem ten minste
Accept
,Content-Type
enOrigin
plus eventuele aangepaste headers op die u wilt ondersteunen.
Code voor automatische preflightaanvraag
Wanneer het CORS-beleid wordt toegepast, ofwel:
- Wereldwijd door
app.UseCors
inProgram.cs
te bellen. - Gebruikmakend van het
[EnableCors]
kenmerk.
ASP.NET Core reageert op de preflight-OPTIES-aanvraag.
In de sectie CORS testen van dit document ziet u dit gedrag.
Kenmerk [HttpOptions] voor preflightverzoeken
Wanneer CORS is ingeschakeld met het juiste beleid, reageert ASP.NET Core in het algemeen automatisch op CORS-voorbereidende aanvragen.
De volgende code maakt gebruik van het kenmerk [HttpOptions] voor het maken van eindpunten voor OPTIONS-aanvragen:
[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);
}
Zie CORS testen met het kenmerk [EnableCors] en de RequireCors-methode voor instructies over het testen van de voorgaande code.
De verlooptijd van de voorbereidende fase instellen
De Access-Control-Max-Age
header geeft aan hoe lang het antwoord op het preflight-verzoek in de cache kan worden opgeslagen. Als u deze header wilt instellen, roept u het volgende SetPreflightMaxAgeaan:
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();
CORS inschakelen op een eindpunt
Hoe CORS werkt
In deze sectie wordt beschreven wat er gebeurt in een CORS-aanvraag op het niveau van de HTTP-berichten.
- CORS is geen beveiligingsfunctie. CORS is een W3C-standaard waarmee een server hetzelfde origin-beleid kan versoepelen.
- Een kwaadwillende actor kan bijvoorbeeld XSS (Cross-Site Scripting) gebruiken op uw site en een cross-site-aanvraag uitvoeren op hun CORS-site om informatie te stelen.
- Een API is niet veiliger door CORS toe te staan.
- Het is aan de client (browser) om CORS af te dwingen. De server voert de aanvraag uit en retourneert het antwoord, het is de client die een fout retourneert en het antwoord blokkeert. Met een van de volgende hulpprogramma's wordt bijvoorbeeld het serverantwoord weergegeven:
- Speelman
- .NET HttpClient
- Een webbrowser door de URL in de adresbalk in te voeren.
- Het is aan de client (browser) om CORS af te dwingen. De server voert de aanvraag uit en retourneert het antwoord, het is de client die een fout retourneert en het antwoord blokkeert. Met een van de volgende hulpprogramma's wordt bijvoorbeeld het serverantwoord weergegeven:
- Het is een manier voor een server om browsers toe te staan een cross-origin XHR - of Fetch API-aanvraag uit te voeren die anders verboden zou zijn.
- Browsers zonder CORS kunnen geen cross-origin-aanvragen uitvoeren. Vóór CORS werd JSONP gebruikt om deze beperking te omzeilen. JSONP gebruikt geen XHR, maar gebruikt de
<script>
tag om het antwoord te ontvangen. Scripts mogen cross-origin worden geladen.
- Browsers zonder CORS kunnen geen cross-origin-aanvragen uitvoeren. Vóór CORS werd JSONP gebruikt om deze beperking te omzeilen. JSONP gebruikt geen XHR, maar gebruikt de
De CORS-specificatie heeft verschillende nieuwe HTTP-headers geïntroduceerd die cross-origin-aanvragen mogelijk maken. Als een browser CORS ondersteunt, worden deze headers automatisch ingesteld voor cross-origin-aanvragen. Aangepaste JavaScript-code is niet vereist om CORS in te schakelen.
Selecteer de knop PUT-test in het geïmplementeerde voorbeeld.
De Origin
koptekst:
- Geeft het domein van de site die het verzoek indient.
- Is vereist en moet afwijken van de host.
Algemene headers
Request URL: https://cors1.azurewebsites.net/api/values
Request Method: GET
Status Code: 200 OK
Antwoordheaders
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
Verzoekheaders
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
aanvragen stelt de server de header AntwoordheadersAccess-Control-Allow-Origin: {allowed origin}
in het antwoord in. In de voorbeeldcode bevat de Delete [EnableCors]
knopaanvraag OPTIONS
bijvoorbeeld de volgende headers:
Algemene headers
Request URL: https://cors3.azurewebsites.net/api/TodoItems2/MyDelete2/5
Request Method: OPTIONS
Status Code: 204 No Content
Antwoordheaders
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
Verzoekheaders
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 de voorgaande antwoordheaders stelt de server in het antwoord de header Access-Control-Allow-Origin in. De https://cors1.azurewebsites.net
waarde van deze header komt overeen met de Origin
header van de aanvraag.
Als AllowAnyOrigin wordt aangeroepen, wordt de Access-Control-Allow-Origin: *
, de jokertekenwaarde, geretourneerd.
AllowAnyOrigin
staat elke oorsprong toe.
Als het antwoord de header niet bevat Access-Control-Allow-Origin
, mislukt de cross-origin-aanvraag. De browser staat de aanvraag met name niet toe. Zelfs als de server een geslaagd antwoord retourneert, maakt de browser het antwoord niet beschikbaar voor de client-app.
HTTP-omleiding naar HTTPS veroorzaakt ERR_INVALID_REDIRECT op de preflight CORS-verzoek
Aanvragen naar een eindpunt met HTTP die door UseHttpsRedirection worden omgeleid naar HTTPS, mislukken met ERR_INVALID_REDIRECT on the CORS preflight request
.
API-projecten kunnen HTTP-aanvragen weigeren in plaats van te gebruiken UseHttpsRedirection
om aanvragen om te leiden naar HTTPS.
CORS in IIS
Bij de implementatie in IIS moet CORS worden uitgevoerd vóór Windows-verificatie als de server niet is geconfigureerd om anonieme toegang toe te staan. Ter ondersteuning van dit scenario moet de IIS CORS-module worden geïnstalleerd en geconfigureerd voor de app.
CORS testen
Het voorbeelddownload bevat code om CORS te testen. Zie hoe ukunt downloaden. Het voorbeeld is een API-project met Razor Pages toegevoegd:
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();
Waarschuwing
WithOrigins("https://localhost:<port>");
mag alleen worden gebruikt voor het testen van een voorbeeld-app die vergelijkbaar is met de voorbeeldcode voor het downloaden.
ValuesController
Hieronder vindt u de eindpunten voor het testen:
[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 wordt geleverd door het Rick.Docs.Samples.RouteInfo NuGet-pakket en toont routegegevens.
Test de voorgaande voorbeeldcode met behulp van een van de volgende methoden:
- Voer het voorbeeld uit met
dotnet run
behulp van de standaard-URL vanhttps://localhost:5001
. - Voer het voorbeeld uit vanuit Visual Studio met de poort ingesteld op 44398 voor een URL van
https://localhost:44398
.
Een browser gebruiken met de F12-hulpprogramma's:
Selecteer de knop Waarden en controleer de kopteksten op het tabblad Netwerk .
Selecteer de PUT-test knop. Zie WeergaveOPTIES-aanvragen voor instructies over het weergeven van de OPTIONS-aanvraag. De PUT-test maakt twee aanvragen, een OPTIONS preflight-aanvraag en een PUT-aanvraag.
Selecteer de
GetValues2 [DisableCors]
knop om een mislukte CORS-aanvraag te activeren. Zoals vermeld in het document, retourneert het antwoord 200 succes, maar wordt het CORS-verzoek niet gedaan. Selecteer het tabblad Console om de CORS-fout weer te geven. Afhankelijk van de browser wordt een fout weergegeven die lijkt op het volgende:Toegang voor het ophalen van
'https://cors1.azurewebsites.net/api/values/GetValues2'
vanaf oorsprong'https://cors3.azurewebsites.net'
is geblokkeerd door het CORS-beleid: Er is geen 'Access-Control-Allow-Origin' header aanwezig op de aangevraagde resource. Als een ondoorzichtig antwoord aan uw behoeften voldoet, stelt u de modus van de aanvraag in op 'no-cors' om de resource op te halen waarvoor CORS is uitgeschakeld.
CORS-eindpunten kunnen worden getest met een hulpprogramma, zoals curl of Fiddler. Wanneer u een hulpprogramma gebruikt, moet de oorsprong van de aanvraag die is opgegeven door de Origin
header verschillen van de host die de aanvraag ontvangt. Als de aanvraag niet cross-origin is op basis van de waarde van de Origin
header:
- Cors Middleware is niet nodig om de aanvraag te verwerken.
- CORS-headers worden niet geretourneerd in het antwoord.
Met de volgende opdracht curl
wordt een OPTIONS-aanvraag met informatie verzonden:
curl -X OPTIONS https://cors3.azurewebsites.net/api/TodoItems2/5 -i
CORS testen met het kenmerk [EnableCors] en de RequireCors-methode
Houd rekening met de volgende code die eindpuntroutering gebruikt om CORS per eindpunt in te schakelen met behulp van 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();
Merk op dat alleen het /echo
eindpunt het gebruik van RequireCors
toestaat om cross-origin aanvragen mogelijk te maken volgens het opgegeven beleid. De onderstaande controllers schakelen CORS in met behulp van het kenmerk [EnableCors].
TodoItems1Controller
Hieronder vindt u eindpunten voor het testen:
[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);
}
De knoppen Delete [EnableCors] en GET [EnableCors] slagen, omdat de eindpunten [EnableCors]
hebben voor preflight-aanvragen en daarop reageren. De andere eindpunten mislukken. De get-knop mislukt, omdat javaScript het volgende verzendt:
headers: {
"Content-Type": "x-custom-header"
},
Het volgende TodoItems2Controller
biedt vergelijkbare eindpunten, maar bevat expliciete code om te reageren op OPTIONS-aanvragen:
[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);
}
De voorgaande code kan worden getest door het voorbeeld te implementeren in Azure.In de vervolgkeuzelijst Controller , preflight te selecteren en vervolgens Controller in te stellen. Alle CORS-aanroepen naar de TodoItems2Controller
eindpunten zijn geslaagd.
Aanvullende bronnen
Door Rick Anderson en Kirk Larkin
In dit artikel wordt beschreven hoe u CORS inschakelt in een ASP.NET Core-app.
Browserbeveiliging voorkomt dat een webpagina aanvragen indient naar een ander domein dan het domein dat de webpagina heeft geleverd. Deze beperking wordt het same-origin policy genoemd. Hetzelfde origin-beleid voorkomt dat een kwaadwillende site gevoelige gegevens van een andere site leest. Soms wilt u toestaan dat andere sites cross-origin-aanvragen indienen bij uw app. Zie het Mozilla CORS-artikel voor meer informatie.
Cross Origin Resource Sharing (CORS):
- Is een W3C-standaard waarmee een server hetzelfde origin-beleid kan versoepelen.
- Is geen beveiligingsfunctie, CORS maakt de beveiliging soepeler. Een API is niet veiliger door CORS toe te staan. Zie Hoe CORS werkt voor meer informatie.
- Hiermee staat u een server toe om bepaalde cross-origin-aanvragen expliciet toe te staan terwijl andere aanvragen worden geweigerd.
- Is veiliger en flexibeler dan eerdere technieken, zoals JSONP.
Voorbeeldcode bekijken of downloaden (hoe download je)
Dezelfde oorsprong
Twee URL's hebben dezelfde oorsprong als ze identieke schema's, hosts en poorten (RFC 6454) hebben.
Deze twee URL's hebben dezelfde oorsprong:
https://example.com/foo.html
https://example.com/bar.html
Deze URL's hebben verschillende oorsprongen dan de vorige twee URL's:
-
https://example.net
: Ander domein -
https://www.example.com/foo.html
: Ander subdomein -
http://example.com/foo.html
: Verschillend schema -
https://example.com:9000/foo.html
: Andere poort
CORS inschakelen
Er zijn drie manieren om CORS in te schakelen:
- In middleware met behulp van een benoemd beleid of standaardbeleid.
- Het gebruik van eindpuntroutering.
- Met het kenmerk [EnableCors] .
Het gebruik van het kenmerk [EnableCors] met een benoemd beleid biedt het beste beheer voor het beperken van eindpunten die CORS ondersteunen.
Waarschuwing
UseCors moet in de juiste volgorde worden aangeroepen. Zie Middleware-bestelling voor meer informatie. Moet bijvoorbeeld UseCors
worden aangeroepen voordat UseResponseCaching wanneer UseResponseCaching
wordt gebruikt.
Elke benadering wordt in de volgende secties beschreven.
CORS met benoemd beleid en middleware
CORS Middleware verwerkt cross-origin-aanvragen. Met de volgende code wordt een CORS-beleid toegepast op alle eindpunten van de app met de opgegeven oorsprongen:
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();
De voorgaande code:
- Hiermee stelt u de beleidsnaam in op
_myAllowSpecificOrigins
. De beleidsnaam is willekeurig. - Roept de UseCors extensiemethode aan en geeft het
_myAllowSpecificOrigins
CORS-beleid op.UseCors
voegt de CORS-middleware toe. De aanroep naarUseCors
moet worden geplaatst nadatUseRouting
, maar vóórUseAuthorization
. Zie Middleware-bestelling voor meer informatie. - Aanroepen AddCors met een lambda-expressie. De lambda neemt een CorsPolicyBuilder object.
Configuratieopties, zoals
WithOrigins
, worden verderop in dit artikel beschreven. - Hiermee schakelt u het
_myAllowSpecificOrigins
CORS-beleid in voor alle controllereindpunten. Zie eindpuntroutering om een CORS-beleid toe te passen op specifieke eindpunten. - Wanneer u Middleware voor antwoordcaching gebruikt, roept u UseCors eerder UseResponseCachingaan.
Met eindpuntroutering moet de CORS-middleware worden geconfigureerd voor uitvoering tussen de aanroepen naar UseRouting
en UseEndpoints
.
Met de AddCors methodeoproep worden CORS-services toegevoegd aan de servicecontainer van de app:
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();
Zie CORS-beleidsopties in dit document voor meer informatie.
De CorsPolicyBuilder methoden kunnen worden gekoppeld, zoals wordt weergegeven in de volgende code:
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();
Opmerking: de opgegeven URL mag geen afsluitende slash (/
) bevatten. Als de URL eindigt met /
, levert de vergelijking false
op en wordt er geen header geretourneerd.
Waarschuwing
UseCors
moet na UseRouting
en vóór UseAuthorization
worden geplaatst. Dit is om ervoor te zorgen dat CORS-headers worden opgenomen in het antwoord voor geautoriseerde en niet-geautoriseerde aanroepen.
Volgorde van UseCors en UseStaticFiles
UseStaticFiles
Normaal gesproken wordt het eerder UseCors
aangeroepen. Apps die JavaScript gebruiken om statische bestanden cross-site op te halen, moeten UseCors
aanroepen voordat ze UseStaticFiles
.
CORS met standaardbeleid en middleware
Met de volgende gemarkeerde code wordt het standaard CORS-beleid ingeschakeld:
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();
Met de voorgaande code wordt het standaard CORS-beleid toegepast op alle controllereindpunten.
Cors met eindpuntroutering inschakelen
Het inschakelen van CORS per eindpunt RequireCors
biedt geen ondersteuning voor automatische voorbereidende aanvragen. Zie dit GitHub-probleem en test CORS met eindpuntroutering en [HttpOptions]voor meer informatie.
Met eindpuntroutering kan CORS per eindpunt worden ingeschakeld met behulp van de RequireCors set extensiemethoden:
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();
In de voorgaande code:
-
app.UseCors
schakelt de CORS-middleware in. Omdat er geen standaardbeleid is geconfigureerd, maaktapp.UseCors()
alleen CORS niet mogelijk. - De
/echo
- en controle-eindpunten staan cross-origin-aanvragen toe met behulp van het opgegeven beleid. - De
/echo2
en Razor Pagina-eindpunten staan geen cross-origin-aanvragen toe omdat er geen standaardbeleid is opgegeven.
Het kenmerk [DisableCors] schakelt niet de CORS uit die is ingeschakeld door eindpuntroutering met RequireCors
.
Zie CORS testen met eindpuntroutering en [HttpOptions] voor instructies over het testen van code die vergelijkbaar is met de voorgaande.
CORS met kenmerken inschakelen
Het inschakelen van CORS met het kenmerk [EnableCors] en het toepassen van een benoemd beleid op alleen die eindpunten waarvoor CORS is vereist, biedt het beste beheer.
Het kenmerk [EnableCors] biedt een alternatief voor het wereldwijd toepassen van CORS. Met [EnableCors]
het kenmerk wordt CORS ingeschakeld voor geselecteerde eindpunten, in plaats van alle eindpunten:
-
[EnableCors]
hiermee geeft u het standaardbeleid. -
[EnableCors("{Policy String}")]
specificeert een benoemd beleid.
Het [EnableCors]
kenmerk kan worden toegepast op:
-
Razor Bladzijde
PageModel
- Controleur
- Controller-actiemethode
Verschillende beleidsregels kunnen worden toegepast op controllers, paginamodellen of actiemethoden met het [EnableCors]
kenmerk. Wanneer het [EnableCors]
kenmerk wordt toegepast op een controller, paginamodel of actiemethode en CORS is ingeschakeld in middleware, worden beide beleidsregels toegepast. Wij raden aan om beleidsregels niet te combineren. Gebruik de
[EnableCors]
kenmerk of middleware, niet beide in dezelfde app.
Met de volgende code wordt een ander beleid toegepast op elke methode:
[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(),
};
}
}
Met de volgende code worden twee CORS-beleidsregels gemaakt:
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();
Voor de beste controle over het beperken van CORS-aanvragen:
- Gebruik
[EnableCors("MyPolicy")]
met een genaamd beleid. - Definieer geen standaardbeleid.
- Gebruik geen eindpuntroutering.
De code in de volgende sectie voldoet aan de voorgaande lijst.
CORS uitschakelen
Het kenmerk [DisableCors] schakelt CORS die is ingeschakeld door eindpuntrouteringniet uit.
De volgende code definieert het CORS-beleid "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();
Met de volgende code wordt CORS uitgeschakeld voor de GetValues2
actie:
[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();
}
De voorgaande code:
- CORS wordt niet ingeschakeld met eindpuntroutering.
- Definieert geen standaard CORS-beleid.
- Gebruikt [EnableCors("MyPolicy")] om het
"MyPolicy"
CORS-beleid voor de controller in te schakelen. - Hiermee schakelt u CORS voor de
GetValues2
methode uit.
Zie CORS testen voor instructies over het testen van de voorgaande code.
CORS-beleidsopties
In deze sectie worden de verschillende opties beschreven die kunnen worden ingesteld in een CORS-beleid:
- De toegestane oorsprongen instellen
- De toegestane HTTP-methoden instellen
- De toegestane aanvraagheaders instellen
- De weergegeven antwoordheaders instellen
- Inloggegevens in cross-origin-aanvragen
- De verlooptijd van de voorbereidende fase instellen
AddPolicy wordt ingeroepen in Program.cs
. Voor sommige opties kan het nuttig zijn om eerst de sectie Hoe CORS werkt te lezen.
De toegestane oorsprongen instellen
AllowAnyOrigin: Hiermee staat u CORS-aanvragen van alle oorsprongen toe met elk schema (http
of https
).
AllowAnyOrigin
is onveilig omdat elke website cross-origin aanvragen kan indienen bij de app.
Opmerking
Het opgeven van AllowAnyOrigin
en AllowCredentials
is een onveilige configuratie en leidt tot cross-site request-vervalsing. De CORS-service retourneert een ongeldig CORS-antwoord wanneer een app is geconfigureerd met beide methoden.
AllowAnyOrigin
beïnvloedt preflight-aanvragen en de Access-Control-Allow-Origin
-koptekst. Zie de sectie Voorbereidende aanvragen voor meer informatie.
SetIsOriginAllowedToAllowWildcardSubdomains: Hiermee stelt u de IsOriginAllowed eigenschap van het beleid in als een functie waarmee origins overeenkomen met een geconfigureerd wildcarddomein bij het evalueren of de oorsprong is toegestaan.
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();
De toegestane HTTP-methoden instellen
- Hiermee staat u elke HTTP-methode toe:
- Beïnvloedt voorbereidende aanvragen en de
Access-Control-Allow-Methods
-header. Zie de sectie Voorbereidende aanvragen voor meer informatie.
De toegestane aanvraagheaders instellen
Als u wilt toestaan dat specifieke headers worden verzonden in een CORS-aanvraag, genaamd headers van auteursaanvragen, roept WithHeaders u de toegestane headers aan en geeft u de toegestane headers op:
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();
Als u alle auteursaanvraagheaders wilt toestaan, roept u het volgende AllowAnyHeaderaan:
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
beïnvloedt preflight-aanvragen en de Access-Control-Request-Headers-header. Zie de sectie Voorbereidende aanvragen voor meer informatie.
Een CORS Middleware-beleid matcht met specifieke headers gespecificeerd door WithHeaders
alleen wanneer de headers in Access-Control-Request-Headers
exact overeenkomen met de headers die zijn gespecificeerd in WithHeaders
.
Denk bijvoorbeeld aan een app die als volgt is geconfigureerd:
app.UseCors(policy => policy.WithHeaders(HeaderNames.CacheControl));
CORS Middleware weigert een voorafgaande aanvraag met de volgende aanvraagheader omdat Content-Language
(HeaderNames.ContentLanguage) niet wordt vermeld in WithHeaders
:
Access-Control-Request-Headers: Cache-Control, Content-Language
De app retourneert een 200 OK-antwoord , maar stuurt de CORS-headers niet terug. Daarom probeert de browser de cross-origin-aanvraag niet uit te voeren.
De weergegeven antwoordheaders instellen
Standaard worden in de browser niet alle antwoordheaders voor de app weergegeven. Zie W3C Cross-Origin Resource Sharing (Terminologie): Simple Response Header voor meer informatie.
De antwoordheaders die standaard beschikbaar zijn, zijn:
Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma
De CORS-specificatie roept deze headers eenvoudige antwoordheaders aan. Als u andere headers beschikbaar wilt maken voor de app, roept u het volgende WithExposedHeadersaan:
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();
Inloggegevens in cross-origin-aanvragen
Referenties vereisen speciale verwerking in een CORS-aanvraag. Standaard verzendt de browser geen inloggegevens met een cross-origin-aanvraag. Inloggegevens omvatten cookies en HTTP-authenticatieschema's. Om referenties met een cross-origin verzoek mee te sturen, moet de client XMLHttpRequest.withCredentials
instellen op true
.
Gebruik rechtstreeks XMLHttpRequest
:
var xhr = new XMLHttpRequest();
xhr.open('get', 'https://www.example.com/api/test');
xhr.withCredentials = true;
JQuery gebruiken:
$.ajax({
type: 'get',
url: 'https://www.example.com/api/test',
xhrFields: {
withCredentials: true
}
});
fetch('https://www.example.com/api/test', {
credentials: 'include'
});
De server moet de inloggegevens toestaan. Als u referenties voor meerdere oorsprongen wilt toestaan, roept u AllowCredentials op.
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();
Het HTTP-antwoord bevat een Access-Control-Allow-Credentials
header, waarmee de browser aangeeft dat de server referenties toestaat voor een cross-origin-aanvraag.
Als de browser referenties verzendt, maar het antwoord geen geldige Access-Control-Allow-Credentials
header bevat, geeft de browser het antwoord niet beschikbaar aan de app en mislukt de cross-origin-aanvraag.
Het toestaan van cross-origin credentials is een beveiligingsrisico. Een website in een ander domein kan de referenties van een aangemelde gebruiker namens de gebruiker verzenden naar de app zonder dat de gebruiker dit weet.
De CORS-specificatie geeft ook aan dat het instellen van origins op "*"
(alle origins) ongeldig is als de Access-Control-Allow-Credentials
header aanwezig is.
Preflight-verzoeken
Voor sommige CORS-aanvragen verzendt de browser een extra OPTIONS-aanvraag voordat de werkelijke aanvraag wordt ingediend. Deze aanvraag wordt een voorbereidende aanvraag genoemd. De browser kan de voorbereidende aanvraag overslaan als aan alle volgende voorwaarden wordt voldaan:
- De aanvraagmethode is GET, HEAD of POST.
- De app stelt geen andere aanvraagheaders in dan
Accept
,Accept-Language
,Content-Language
,Content-Type
ofLast-Event-ID
. - De
Content-Type
header, indien ingesteld, heeft een van de volgende waarden:application/x-www-form-urlencoded
multipart/form-data
text/plain
De regel voor aanvraagheaders die zijn ingesteld voor de clientaanvraag is van toepassing op headers die door de app worden ingesteld door setRequestHeader
aan te roepen op het XMLHttpRequest
-object. De CORS-specificatie noemt deze headers auteursaanvraagheaders. De regel is niet van toepassing op headers die de browser kan instellen, zoals User-Agent
, Host
of Content-Length
.
Hier volgt een voorbeeld van een antwoord dat lijkt op het preflight-verzoek dat is gedaan via de knop [Put test] in de Test CORS sectie van dit document.
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
Het preflight-verzoek gebruikt de HTTP OPTIONS methode. Het kan de volgende headers bevatten:
- Access-Control-Request-Method: de HTTP-methode die wordt gebruikt voor de werkelijke aanvraag.
-
Access-Control-Request-Headers: een lijst met aanvraagheaders die door de app worden ingesteld voor de werkelijke aanvraag. Zoals eerder vermeld, bevat dit geen headers die door de browser worden ingesteld, zoals
User-Agent
. - Access-Control-Allow-Methods
Als de voorbereidende aanvraag wordt geweigerd, retourneert de app een 200 OK
antwoord, maar de CORS-headers worden niet ingesteld. Daarom probeert de browser de cross-origin-aanvraag niet uit te voeren. Voor een voorbeeld van een geweigerde voorbereidende aanvraag, zie de sectie Test CORS van dit document.
Met de F12-hulpprogramma's wordt in de console-app een fout weergegeven die vergelijkbaar is met een van de volgende, afhankelijk van de browser:
- Firefox: Cross-Origin-aanvraag geblokkeerd: de Same-Origin Policy staat het lezen van de externe resource op
https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5
niet toe. (Reden: CORS-aanvraag is niet geslaagd). Meer informatie - Op basis van Chromium: Toegang tot het ophalen van 'https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5' vanaf oorsprong 'https://cors3.azurewebsites.net' is geblokkeerd door CORS-beleid: Reactie op preflight-verzoek voldoet niet aan de toegangscontrole: Er is geen 'Access-Control-Allow-Origin'-header aanwezig op de opgevraagde resource. Als een ondoorzichtig antwoord aan uw behoeften voldoet, stelt u de modus van de aanvraag in op 'no-cors' om de resource op te halen waarvoor CORS is uitgeschakeld.
Als u specifieke headers wilt toestaan, roept u het volgende aan 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();
Als u alle auteursaanvraagheaders wilt toestaan, roept u het volgende AllowAnyHeaderaan:
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();
Browsers zijn niet consistent in de wijze waarop ze zijn ingesteld Access-Control-Request-Headers
. Als een van beide:
- Kopteksten zijn ingesteld op iets anders dan
"*"
-
AllowAnyHeader wordt aangeroepen: neem ten minste
Accept
,Content-Type
enOrigin
plus eventuele aangepaste headers op die u wilt ondersteunen.
Code voor automatische preflightaanvraag
Wanneer het CORS-beleid wordt toegepast, ofwel:
- Wereldwijd door
app.UseCors
inProgram.cs
te bellen. - Gebruikmakend van het
[EnableCors]
kenmerk.
ASP.NET Core reageert op de preflight-OPTIES-aanvraag.
Het inschakelen van CORS per eindpunt RequireCors
biedt momenteel geen ondersteuning voor automatische preflight-verzoeken.
In de sectie CORS testen van dit document ziet u dit gedrag.
Kenmerk [HttpOptions] voor preflightverzoeken
Wanneer CORS is ingeschakeld met het juiste beleid, reageert ASP.NET Core in het algemeen automatisch op CORS-voorbereidende aanvragen. In sommige scenario's is dit mogelijk niet het geval. Gebruik bijvoorbeeld CORS met eindpuntroutering.
De volgende code maakt gebruik van het kenmerk [HttpOptions] voor het maken van eindpunten voor OPTIONS-aanvragen:
[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);
}
Zie CORS testen met eindpuntroutering en [HttpOptions] voor instructies over het testen van de voorgaande code.
De verlooptijd van de voorbereidende fase instellen
De Access-Control-Max-Age
header geeft aan hoe lang het antwoord op het preflight-verzoek in de cache kan worden opgeslagen. Als u deze header wilt instellen, roept u het volgende SetPreflightMaxAgeaan:
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();
Hoe CORS werkt
In deze sectie wordt beschreven wat er gebeurt in een CORS-aanvraag op het niveau van de HTTP-berichten.
- CORS is geen beveiligingsfunctie. CORS is een W3C-standaard waarmee een server hetzelfde origin-beleid kan versoepelen.
- Een kwaadwillende actor kan bijvoorbeeld XSS (Cross-Site Scripting) gebruiken op uw site en een cross-site-aanvraag uitvoeren op hun CORS-site om informatie te stelen.
- Een API is niet veiliger door CORS toe te staan.
- Het is aan de client (browser) om CORS af te dwingen. De server voert de aanvraag uit en retourneert het antwoord, het is de client die een fout retourneert en het antwoord blokkeert. Met een van de volgende hulpprogramma's wordt bijvoorbeeld het serverantwoord weergegeven:
- Speelman
- .NET HttpClient
- Een webbrowser door de URL in de adresbalk in te voeren.
- Het is aan de client (browser) om CORS af te dwingen. De server voert de aanvraag uit en retourneert het antwoord, het is de client die een fout retourneert en het antwoord blokkeert. Met een van de volgende hulpprogramma's wordt bijvoorbeeld het serverantwoord weergegeven:
- Het is een manier voor een server om browsers toe te staan een cross-origin XHR - of Fetch API-aanvraag uit te voeren die anders verboden zou zijn.
- Browsers zonder CORS kunnen geen cross-origin-aanvragen uitvoeren. Vóór CORS werd JSONP gebruikt om deze beperking te omzeilen. JSONP gebruikt geen XHR, maar gebruikt de
<script>
tag om het antwoord te ontvangen. Scripts mogen cross-origin worden geladen.
- Browsers zonder CORS kunnen geen cross-origin-aanvragen uitvoeren. Vóór CORS werd JSONP gebruikt om deze beperking te omzeilen. JSONP gebruikt geen XHR, maar gebruikt de
De CORS-specificatie heeft verschillende nieuwe HTTP-headers geïntroduceerd die cross-origin-aanvragen mogelijk maken. Als een browser CORS ondersteunt, worden deze headers automatisch ingesteld voor cross-origin-aanvragen. Aangepaste JavaScript-code is niet vereist om CORS in te schakelen.
Dit is een voorbeeld van een cross-origin-aanvraag van de waardentest-knop naar https://cors1.azurewebsites.net/api/values
. De Origin
koptekst:
- Geeft het domein van de site die het verzoek indient.
- Is vereist en moet afwijken van de host.
Algemene headers
Request URL: https://cors1.azurewebsites.net/api/values
Request Method: GET
Status Code: 200 OK
Antwoordheaders
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
Verzoekheaders
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
aanvragen stelt de server de header AntwoordheadersAccess-Control-Allow-Origin: {allowed origin}
in het antwoord in. Het geïmplementeerde voorbeeld, knopaanvraag OPTIONS
Verwijderen, bevat bijvoorbeeld de volgende headers:
Algemene headers
Request URL: https://cors3.azurewebsites.net/api/TodoItems2/MyDelete2/5
Request Method: OPTIONS
Status Code: 204 No Content
Antwoordheaders
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
Verzoekheaders
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 de voorgaande antwoordheaders stelt de server in het antwoord de header Access-Control-Allow-Origin in. De https://cors1.azurewebsites.net
waarde van deze header komt overeen met de Origin
header van de aanvraag.
Als AllowAnyOrigin wordt aangeroepen, wordt de Access-Control-Allow-Origin: *
, de jokertekenwaarde, geretourneerd.
AllowAnyOrigin
staat elke oorsprong toe.
Als het antwoord de header niet bevat Access-Control-Allow-Origin
, mislukt de cross-origin-aanvraag. De browser staat de aanvraag met name niet toe. Zelfs als de server een geslaagd antwoord retourneert, maakt de browser het antwoord niet beschikbaar voor de client-app.
HTTP-omleiding naar HTTPS veroorzaakt ERR_INVALID_REDIRECT op de preflight CORS-verzoek
Aanvragen naar een eindpunt met HTTP die door UseHttpsRedirection worden omgeleid naar HTTPS, mislukken met ERR_INVALID_REDIRECT on the CORS preflight request
.
API-projecten kunnen HTTP-aanvragen weigeren in plaats van te gebruiken UseHttpsRedirection
om aanvragen om te leiden naar HTTPS.
OPTIES-aanvragen weergeven
Standaard worden in de browsers Chrome en Edge geen OPTIES-aanvragen weergegeven op het netwerktabblad van de F12-hulpprogramma's. OPTIES-aanvragen weergeven in deze browsers:
-
chrome://flags/#out-of-blink-cors
ofedge://flags/#out-of-blink-cors
- schakel de vlag uit.
- herstarten.
In Firefox worden OPTIES-aanvragen standaard weergegeven.
CORS in IIS
Bij de implementatie in IIS moet CORS worden uitgevoerd vóór Windows-verificatie als de server niet is geconfigureerd om anonieme toegang toe te staan. Ter ondersteuning van dit scenario moet de IIS CORS-module worden geïnstalleerd en geconfigureerd voor de app.
CORS testen
Het voorbeelddownload bevat code om CORS te testen. Zie hoe ukunt downloaden. Het voorbeeld is een API-project met Razor Pages toegevoegd:
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();
Waarschuwing
WithOrigins("https://localhost:<port>");
mag alleen worden gebruikt voor het testen van een voorbeeld-app die vergelijkbaar is met de voorbeeldcode voor het downloaden.
ValuesController
Hieronder vindt u de eindpunten voor het testen:
[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 wordt geleverd door het Rick.Docs.Samples.RouteInfo NuGet-pakket en toont routegegevens.
Test de voorgaande voorbeeldcode met behulp van een van de volgende methoden:
- Voer het voorbeeld uit met
dotnet run
behulp van de standaard-URL vanhttps://localhost:5001
. - Voer het voorbeeld uit vanuit Visual Studio met de poort ingesteld op 44398 voor een URL van
https://localhost:44398
.
Een browser gebruiken met de F12-hulpprogramma's:
Selecteer de knop Waarden en controleer de kopteksten op het tabblad Netwerk .
Selecteer de PUT-test knop. Zie WeergaveOPTIES-aanvragen voor instructies over het weergeven van de OPTIONS-aanvraag. De PUT-test maakt twee aanvragen, een OPTIONS preflight-aanvraag en een PUT-aanvraag.
Selecteer de
GetValues2 [DisableCors]
knop om een mislukte CORS-aanvraag te activeren. Zoals vermeld in het document, retourneert het antwoord 200 succes, maar wordt het CORS-verzoek niet gedaan. Selecteer het tabblad Console om de CORS-fout weer te geven. Afhankelijk van de browser wordt een fout weergegeven die lijkt op het volgende:Toegang voor het ophalen van
'https://cors1.azurewebsites.net/api/values/GetValues2'
vanaf oorsprong'https://cors3.azurewebsites.net'
is geblokkeerd door het CORS-beleid: Er is geen 'Access-Control-Allow-Origin' header aanwezig op de aangevraagde resource. Als een ondoorzichtig antwoord aan uw behoeften voldoet, stelt u de modus van de aanvraag in op 'no-cors' om de resource op te halen waarvoor CORS is uitgeschakeld.
CORS-eindpunten kunnen worden getest met een hulpprogramma, zoals curl of Fiddler. Wanneer u een hulpprogramma gebruikt, moet de oorsprong van de aanvraag die is opgegeven door de Origin
header verschillen van de host die de aanvraag ontvangt. Als de aanvraag niet cross-origin is op basis van de waarde van de Origin
header:
- Cors Middleware is niet nodig om de aanvraag te verwerken.
- CORS-headers worden niet geretourneerd in het antwoord.
Met de volgende opdracht curl
wordt een OPTIONS-aanvraag met informatie verzonden:
curl -X OPTIONS https://cors3.azurewebsites.net/api/TodoItems2/5 -i
CORS testen met eindpuntroutering en [HttpOptions]
Het inschakelen van CORS per eindpunt RequireCors
ondersteunt momenteel geen automatische preflight-aanvragen. Houd rekening met de volgende code die gebruikmaakt van eindpuntroutering om CORS in te schakelen:
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();
TodoItems1Controller
Hieronder vindt u eindpunten voor het testen:
[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);
}
Test de voorgaande code vanaf de testpagina (https://cors1.azurewebsites.net/test?number=1
) van het geïmplementeerde voorbeeld.
De knoppen Delete [EnableCors] en GET [EnableCors] slagen, omdat de eindpunten [EnableCors]
hebben voor preflight-aanvragen en daarop reageren. De andere eindpunten mislukken. De get-knop mislukt, omdat javaScript het volgende verzendt:
headers: {
"Content-Type": "x-custom-header"
},
Het volgende TodoItems2Controller
biedt vergelijkbare eindpunten, maar bevat expliciete code om te reageren op OPTIONS-aanvragen:
[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);
}
De voorgaande code kan worden getest door het voorbeeld te implementeren in Azure.In de vervolgkeuzelijst Controller , preflight te selecteren en vervolgens Controller in te stellen. Alle CORS-aanroepen naar de TodoItems2Controller
eindpunten zijn geslaagd.
Aanvullende bronnen
Door Rick Anderson en Kirk Larkin
In dit artikel wordt beschreven hoe u CORS inschakelt in een ASP.NET Core-app.
Browserbeveiliging voorkomt dat een webpagina aanvragen indient naar een ander domein dan het domein dat de webpagina heeft geleverd. Deze beperking wordt het same-origin policy genoemd. Hetzelfde origin-beleid voorkomt dat een kwaadwillende site gevoelige gegevens van een andere site leest. Soms wilt u toestaan dat andere sites cross-origin-aanvragen indienen bij uw app. Zie het Mozilla CORS-artikel voor meer informatie.
Cross Origin Resource Sharing (CORS):
- Is een W3C-standaard waarmee een server hetzelfde origin-beleid kan versoepelen.
- Is geen beveiligingsfunctie, CORS maakt de beveiliging soepeler. Een API is niet veiliger door CORS toe te staan. Zie Hoe CORS werkt voor meer informatie.
- Hiermee staat u een server toe om bepaalde cross-origin-aanvragen expliciet toe te staan terwijl andere aanvragen worden geweigerd.
- Is veiliger en flexibeler dan eerdere technieken, zoals JSONP.
Voorbeeldcode bekijken of downloaden (hoe download je)
Dezelfde oorsprong
Twee URL's hebben dezelfde oorsprong als ze identieke schema's, hosts en poorten (RFC 6454) hebben.
Deze twee URL's hebben dezelfde oorsprong:
https://example.com/foo.html
https://example.com/bar.html
Deze URL's hebben verschillende oorsprongen dan de vorige twee URL's:
-
https://example.net
: Ander domein -
https://www.example.com/foo.html
: Ander subdomein -
http://example.com/foo.html
: Verschillend schema -
https://example.com:9000/foo.html
: Andere poort
CORS inschakelen
Er zijn drie manieren om CORS in te schakelen:
- In middleware met behulp van een benoemd beleid of standaardbeleid.
- Het gebruik van eindpuntroutering.
- Met het kenmerk [EnableCors] .
Het gebruik van het kenmerk [EnableCors] met een benoemd beleid biedt het beste beheer voor het beperken van eindpunten die CORS ondersteunen.
Waarschuwing
UseCors moet in de juiste volgorde worden aangeroepen. Zie Middleware-bestelling voor meer informatie. Moet bijvoorbeeld UseCors
worden aangeroepen voordat UseResponseCaching wanneer UseResponseCaching
wordt gebruikt.
Elke benadering wordt in de volgende secties beschreven.
CORS met benoemd beleid en middleware
CORS Middleware verwerkt cross-origin-aanvragen. Met de volgende code wordt een CORS-beleid toegepast op alle eindpunten van de app met de opgegeven oorsprongen:
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();
});
}
}
De voorgaande code:
- Hiermee stelt u de beleidsnaam in op
_myAllowSpecificOrigins
. De beleidsnaam is willekeurig. - Roept de UseCors extensiemethode aan en geeft het
_myAllowSpecificOrigins
CORS-beleid op.UseCors
voegt de CORS-middleware toe. De aanroep naarUseCors
moet worden geplaatst nadatUseRouting
, maar vóórUseAuthorization
. Zie Middleware-bestelling voor meer informatie. - Aanroepen AddCors met een lambda-expressie. De lambda neemt een CorsPolicyBuilder object.
Configuratieopties, zoals
WithOrigins
, worden verderop in dit artikel beschreven. - Hiermee schakelt u het
_myAllowSpecificOrigins
CORS-beleid in voor alle controllereindpunten. Zie eindpuntroutering om een CORS-beleid toe te passen op specifieke eindpunten. - Wanneer u Middleware voor antwoordcaching gebruikt, roept u UseCors eerder UseResponseCachingaan.
Met eindpuntroutering moet de CORS-middleware worden geconfigureerd voor uitvoering tussen de aanroepen naar UseRouting
en UseEndpoints
.
Zie CORS testen voor instructies over het testen van code die vergelijkbaar is met de voorgaande code.
Met de AddCors methodeoproep worden CORS-services toegevoegd aan de servicecontainer van de app:
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();
}
Zie CORS-beleidsopties in dit document voor meer informatie.
De CorsPolicyBuilder methoden kunnen worden gekoppeld, zoals wordt weergegeven in de volgende code:
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();
}
Opmerking: de opgegeven URL mag geen afsluitende slash (/
) bevatten. Als de URL eindigt met /
, levert de vergelijking false
op en wordt er geen header geretourneerd.
CORS met standaardbeleid en middleware
Met de volgende gemarkeerde code wordt het standaard CORS-beleid ingeschakeld:
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();
});
}
}
Met de voorgaande code wordt het standaard CORS-beleid toegepast op alle controllereindpunten.
Cors met eindpuntroutering inschakelen
Het inschakelen van CORS per eindpunt RequireCors
biedt geen ondersteuning voor automatische voorbereidende aanvragen. Zie dit GitHub-probleem en test CORS met eindpuntroutering en [HttpOptions]voor meer informatie.
Met eindpuntroutering kan CORS per eindpunt worden ingeschakeld met behulp van de RequireCors set extensiemethoden:
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();
});
}
}
In de voorgaande code:
-
app.UseCors
schakelt de CORS-middleware in. Omdat er geen standaardbeleid is geconfigureerd, maaktapp.UseCors()
alleen CORS niet mogelijk. - De
/echo
- en controle-eindpunten staan cross-origin-aanvragen toe met behulp van het opgegeven beleid. - De
/echo2
en Razor Pagina-eindpunten staan geen cross-origin-aanvragen toe omdat er geen standaardbeleid is opgegeven.
Het kenmerk [DisableCors] schakelt niet de CORS uit die is ingeschakeld door eindpuntroutering met RequireCors
.
Zie CORS testen met eindpuntroutering en [HttpOptions] voor instructies over het testen van code die vergelijkbaar is met de voorgaande.
CORS met kenmerken inschakelen
Het inschakelen van CORS met het kenmerk [EnableCors] en het toepassen van een benoemd beleid op alleen die eindpunten waarvoor CORS is vereist, biedt het beste beheer.
Het kenmerk [EnableCors] biedt een alternatief voor het wereldwijd toepassen van CORS. Met [EnableCors]
het kenmerk wordt CORS ingeschakeld voor geselecteerde eindpunten, in plaats van alle eindpunten:
-
[EnableCors]
hiermee geeft u het standaardbeleid. -
[EnableCors("{Policy String}")]
specificeert een benoemd beleid.
Het [EnableCors]
kenmerk kan worden toegepast op:
-
Razor Bladzijde
PageModel
- Controleur
- Controller-actiemethode
Verschillende beleidsregels kunnen worden toegepast op controllers, paginamodellen of actiemethoden met het [EnableCors]
kenmerk. Wanneer het [EnableCors]
kenmerk wordt toegepast op een controller, paginamodel of actiemethode en CORS is ingeschakeld in middleware, worden beide beleidsregels toegepast. Wij raden aan om beleidsregels niet te combineren. Gebruik de
[EnableCors]
kenmerk of middleware, niet beide in dezelfde app.
Met de volgende code wordt een ander beleid toegepast op elke methode:
[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(),
};
}
}
Met de volgende code worden twee CORS-beleidsregels gemaakt:
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();
});
}
}
Voor de beste controle over het beperken van CORS-aanvragen:
- Gebruik
[EnableCors("MyPolicy")]
met een genaamd beleid. - Definieer geen standaardbeleid.
- Gebruik geen eindpuntroutering.
De code in de volgende sectie voldoet aan de voorgaande lijst.
Zie CORS testen voor instructies over het testen van code die vergelijkbaar is met de voorgaande code.
CORS uitschakelen
Het kenmerk [DisableCors] schakelt CORS die is ingeschakeld door eindpuntrouteringniet uit.
De volgende code definieert het CORS-beleid "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();
});
}
}
Met de volgende code wordt CORS uitgeschakeld voor de GetValues2
actie:
[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();
}
De voorgaande code:
- CORS wordt niet ingeschakeld met eindpuntroutering.
- Definieert geen standaard CORS-beleid.
- Gebruikt [EnableCors("MyPolicy")] om het
"MyPolicy"
CORS-beleid voor de controller in te schakelen. - Hiermee schakelt u CORS voor de
GetValues2
methode uit.
Zie CORS testen voor instructies over het testen van de voorgaande code.
CORS-beleidsopties
In deze sectie worden de verschillende opties beschreven die kunnen worden ingesteld in een CORS-beleid:
- De toegestane oorsprongen instellen
- De toegestane HTTP-methoden instellen
- De toegestane aanvraagheaders instellen
- De weergegeven antwoordheaders instellen
- Inloggegevens in cross-origin-aanvragen
- De verlooptijd van de voorbereidende fase instellen
AddPolicy wordt ingeroepen in Startup.ConfigureServices
. Voor sommige opties kan het nuttig zijn om eerst de sectie Hoe CORS werkt te lezen.
De toegestane oorsprongen instellen
AllowAnyOrigin: Hiermee staat u CORS-aanvragen van alle oorsprongen toe met elk schema (http
of https
).
AllowAnyOrigin
is onveilig omdat elke website cross-origin aanvragen kan indienen bij de app.
Opmerking
Het opgeven van AllowAnyOrigin
en AllowCredentials
is een onveilige configuratie en leidt tot cross-site request-vervalsing. De CORS-service retourneert een ongeldig CORS-antwoord wanneer een app is geconfigureerd met beide methoden.
AllowAnyOrigin
beïnvloedt preflight-aanvragen en de Access-Control-Allow-Origin
-koptekst. Zie de sectie Voorbereidende aanvragen voor meer informatie.
SetIsOriginAllowedToAllowWildcardSubdomains: Hiermee stelt u de IsOriginAllowed eigenschap van het beleid in als een functie waarmee origins overeenkomen met een geconfigureerd wildcarddomein bij het evalueren of de oorsprong is toegestaan.
options.AddPolicy("MyAllowSubdomainPolicy",
policy =>
{
policy.WithOrigins("https://*.example.com")
.SetIsOriginAllowedToAllowWildcardSubdomains();
});
De toegestane HTTP-methoden instellen
- Hiermee staat u elke HTTP-methode toe:
- Beïnvloedt voorbereidende aanvragen en de
Access-Control-Allow-Methods
-header. Zie de sectie Voorbereidende aanvragen voor meer informatie.
De toegestane aanvraagheaders instellen
Als u wilt toestaan dat specifieke headers worden verzonden in een CORS-aanvraag, genaamd headers van auteursaanvragen, roept WithHeaders u de toegestane headers aan en geeft u de toegestane headers op:
options.AddPolicy("MyAllowHeadersPolicy",
policy =>
{
// requires using Microsoft.Net.Http.Headers;
policy.WithOrigins("http://example.com")
.WithHeaders(HeaderNames.ContentType, "x-custom-header");
});
Als u alle auteursaanvraagheaders wilt toestaan, roept u het volgende AllowAnyHeaderaan:
options.AddPolicy("MyAllowAllHeadersPolicy",
policy =>
{
policy.WithOrigins("https://*.example.com")
.AllowAnyHeader();
});
AllowAnyHeader
beïnvloedt preflight-aanvragen en de Access-Control-Request-Headers-header. Zie de sectie Voorbereidende aanvragen voor meer informatie.
Een CORS Middleware-beleid matcht met specifieke headers gespecificeerd door WithHeaders
alleen wanneer de headers in Access-Control-Request-Headers
exact overeenkomen met de headers die zijn gespecificeerd in WithHeaders
.
Denk bijvoorbeeld aan een app die als volgt is geconfigureerd:
app.UseCors(policy => policy.WithHeaders(HeaderNames.CacheControl));
CORS Middleware weigert een voorafgaande aanvraag met de volgende aanvraagheader omdat Content-Language
(HeaderNames.ContentLanguage) niet wordt vermeld in WithHeaders
:
Access-Control-Request-Headers: Cache-Control, Content-Language
De app retourneert een 200 OK-antwoord , maar stuurt de CORS-headers niet terug. Daarom probeert de browser de cross-origin-aanvraag niet uit te voeren.
De weergegeven antwoordheaders instellen
Standaard worden in de browser niet alle antwoordheaders voor de app weergegeven. Zie W3C Cross-Origin Resource Sharing (Terminologie): Simple Response Header voor meer informatie.
De antwoordheaders die standaard beschikbaar zijn, zijn:
Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma
De CORS-specificatie roept deze headers eenvoudige antwoordheaders aan. Als u andere headers beschikbaar wilt maken voor de app, roept u het volgende WithExposedHeadersaan:
options.AddPolicy("MyExposeResponseHeadersPolicy",
policy =>
{
policy.WithOrigins("https://*.example.com")
.WithExposedHeaders("x-custom-header");
});
Inloggegevens in cross-origin-aanvragen
Referenties vereisen speciale verwerking in een CORS-aanvraag. Standaard verzendt de browser geen inloggegevens met een cross-origin-aanvraag. Inloggegevens omvatten cookies en HTTP-authenticatieschema's. Om referenties met een cross-origin verzoek mee te sturen, moet de client XMLHttpRequest.withCredentials
instellen op true
.
Gebruik rechtstreeks XMLHttpRequest
:
var xhr = new XMLHttpRequest();
xhr.open('get', 'https://www.example.com/api/test');
xhr.withCredentials = true;
JQuery gebruiken:
$.ajax({
type: 'get',
url: 'https://www.example.com/api/test',
xhrFields: {
withCredentials: true
}
});
fetch('https://www.example.com/api/test', {
credentials: 'include'
});
De server moet de inloggegevens toestaan. Als u referenties voor meerdere oorsprongen wilt toestaan, roept u AllowCredentials op.
options.AddPolicy("MyMyAllowCredentialsPolicy",
policy =>
{
policy.WithOrigins("http://example.com")
.AllowCredentials();
});
Het HTTP-antwoord bevat een Access-Control-Allow-Credentials
header, waarmee de browser aangeeft dat de server referenties toestaat voor een cross-origin-aanvraag.
Als de browser referenties verzendt, maar het antwoord geen geldige Access-Control-Allow-Credentials
header bevat, geeft de browser het antwoord niet beschikbaar aan de app en mislukt de cross-origin-aanvraag.
Het toestaan van cross-origin credentials is een beveiligingsrisico. Een website in een ander domein kan de referenties van een aangemelde gebruiker namens de gebruiker verzenden naar de app zonder dat de gebruiker dit weet.
De CORS-specificatie geeft ook aan dat het instellen van origins op "*"
(alle origins) ongeldig is als de Access-Control-Allow-Credentials
header aanwezig is.
Preflight-verzoeken
Voor sommige CORS-aanvragen verzendt de browser een extra OPTIONS-aanvraag voordat de werkelijke aanvraag wordt ingediend. Deze aanvraag wordt een voorbereidende aanvraag genoemd. De browser kan de voorbereidende aanvraag overslaan als aan alle volgende voorwaarden wordt voldaan:
- De aanvraagmethode is GET, HEAD of POST.
- De app stelt geen andere aanvraagheaders in dan
Accept
,Accept-Language
,Content-Language
,Content-Type
ofLast-Event-ID
. - De
Content-Type
header, indien ingesteld, heeft een van de volgende waarden:application/x-www-form-urlencoded
multipart/form-data
text/plain
De regel voor aanvraagheaders die zijn ingesteld voor de clientaanvraag is van toepassing op headers die door de app worden ingesteld door setRequestHeader
aan te roepen op het XMLHttpRequest
-object. De CORS-specificatie noemt deze headers auteursaanvraagheaders. De regel is niet van toepassing op headers die de browser kan instellen, zoals User-Agent
, Host
of Content-Length
.
Hier volgt een voorbeeld van een antwoord dat lijkt op het preflight-verzoek dat is gedaan via de knop [Put test] in de Test CORS sectie van dit document.
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
Het preflight-verzoek gebruikt de HTTP OPTIONS methode. Het kan de volgende headers bevatten:
- Access-Control-Request-Method: de HTTP-methode die wordt gebruikt voor de werkelijke aanvraag.
-
Access-Control-Request-Headers: een lijst met aanvraagheaders die door de app worden ingesteld voor de werkelijke aanvraag. Zoals eerder vermeld, bevat dit geen headers die door de browser worden ingesteld, zoals
User-Agent
. - Access-Control-Allow-Methods
Als de voorbereidende aanvraag wordt geweigerd, retourneert de app een 200 OK
antwoord, maar de CORS-headers worden niet ingesteld. Daarom probeert de browser de cross-origin-aanvraag niet uit te voeren. Voor een voorbeeld van een geweigerde voorbereidende aanvraag, zie de sectie Test CORS van dit document.
Met de F12-hulpprogramma's wordt in de console-app een fout weergegeven die vergelijkbaar is met een van de volgende, afhankelijk van de browser:
- Firefox: Cross-Origin-aanvraag geblokkeerd: de Same-Origin Policy staat het lezen van de externe resource op
https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5
niet toe. (Reden: CORS-aanvraag is niet geslaagd). Meer informatie - Op basis van Chromium: Toegang tot het ophalen van 'https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5' vanaf oorsprong 'https://cors3.azurewebsites.net' is geblokkeerd door CORS-beleid: Reactie op preflight-verzoek voldoet niet aan de toegangscontrole: Er is geen 'Access-Control-Allow-Origin'-header aanwezig op de opgevraagde resource. Als een ondoorzichtig antwoord aan uw behoeften voldoet, stelt u de modus van de aanvraag in op 'no-cors' om de resource op te halen waarvoor CORS is uitgeschakeld.
Als u specifieke headers wilt toestaan, roept u het volgende aan WithHeaders:
options.AddPolicy("MyAllowHeadersPolicy",
policy =>
{
// requires using Microsoft.Net.Http.Headers;
policy.WithOrigins("http://example.com")
.WithHeaders(HeaderNames.ContentType, "x-custom-header");
});
Als u alle auteursaanvraagheaders wilt toestaan, roept u het volgende AllowAnyHeaderaan:
options.AddPolicy("MyAllowAllHeadersPolicy",
policy =>
{
policy.WithOrigins("https://*.example.com")
.AllowAnyHeader();
});
Browsers zijn niet consistent in de wijze waarop ze zijn ingesteld Access-Control-Request-Headers
. Als een van beide:
- Kopteksten zijn ingesteld op iets anders dan
"*"
-
AllowAnyHeader wordt aangeroepen: neem ten minste
Accept
,Content-Type
enOrigin
plus eventuele aangepaste headers op die u wilt ondersteunen.
Code voor automatische preflightaanvraag
Wanneer het CORS-beleid wordt toegepast, ofwel:
- Wereldwijd door
app.UseCors
inStartup.Configure
te bellen. - Gebruikmakend van het
[EnableCors]
kenmerk.
ASP.NET Core reageert op de preflight-OPTIES-aanvraag.
Het inschakelen van CORS per eindpunt RequireCors
biedt momenteel geen ondersteuning voor automatische preflight-verzoeken.
In de sectie CORS testen van dit document ziet u dit gedrag.
Kenmerk [HttpOptions] voor preflightverzoeken
Wanneer CORS is ingeschakeld met het juiste beleid, reageert ASP.NET Core in het algemeen automatisch op CORS-voorbereidende aanvragen. In sommige scenario's is dit mogelijk niet het geval. Gebruik bijvoorbeeld CORS met eindpuntroutering.
De volgende code maakt gebruik van het kenmerk [HttpOptions] voor het maken van eindpunten voor OPTIONS-aanvragen:
[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);
}
Zie CORS testen met eindpuntroutering en [HttpOptions] voor instructies over het testen van de voorgaande code.
De verlooptijd van de voorbereidende fase instellen
De Access-Control-Max-Age
header geeft aan hoe lang het antwoord op het preflight-verzoek in de cache kan worden opgeslagen. Als u deze header wilt instellen, roept u het volgende SetPreflightMaxAgeaan:
options.AddPolicy("MySetPreflightExpirationPolicy",
policy =>
{
policy.WithOrigins("http://example.com")
.SetPreflightMaxAge(TimeSpan.FromSeconds(2520));
});
Hoe CORS werkt
In deze sectie wordt beschreven wat er gebeurt in een CORS-aanvraag op het niveau van de HTTP-berichten.
- CORS is geen beveiligingsfunctie. CORS is een W3C-standaard waarmee een server hetzelfde origin-beleid kan versoepelen.
- Een kwaadwillende actor kan bijvoorbeeld XSS (Cross-Site Scripting) gebruiken op uw site en een cross-site-aanvraag uitvoeren op hun CORS-site om informatie te stelen.
- Een API is niet veiliger door CORS toe te staan.
- Het is aan de client (browser) om CORS af te dwingen. De server voert de aanvraag uit en retourneert het antwoord, het is de client die een fout retourneert en het antwoord blokkeert. Met een van de volgende hulpprogramma's wordt bijvoorbeeld het serverantwoord weergegeven:
- Speelman
- .NET HttpClient
- Een webbrowser door de URL in de adresbalk in te voeren.
- Het is aan de client (browser) om CORS af te dwingen. De server voert de aanvraag uit en retourneert het antwoord, het is de client die een fout retourneert en het antwoord blokkeert. Met een van de volgende hulpprogramma's wordt bijvoorbeeld het serverantwoord weergegeven:
- Het is een manier voor een server om browsers toe te staan een cross-origin XHR - of Fetch API-aanvraag uit te voeren die anders verboden zou zijn.
- Browsers zonder CORS kunnen geen cross-origin-aanvragen uitvoeren. Vóór CORS werd JSONP gebruikt om deze beperking te omzeilen. JSONP gebruikt geen XHR, maar gebruikt de
<script>
tag om het antwoord te ontvangen. Scripts mogen cross-origin worden geladen.
- Browsers zonder CORS kunnen geen cross-origin-aanvragen uitvoeren. Vóór CORS werd JSONP gebruikt om deze beperking te omzeilen. JSONP gebruikt geen XHR, maar gebruikt de
De CORS-specificatie heeft verschillende nieuwe HTTP-headers geïntroduceerd die cross-origin-aanvragen mogelijk maken. Als een browser CORS ondersteunt, worden deze headers automatisch ingesteld voor cross-origin-aanvragen. Aangepaste JavaScript-code is niet vereist om CORS in te schakelen.
Dit is een voorbeeld van een cross-origin-aanvraag van de waardentest-knop naar https://cors1.azurewebsites.net/api/values
. De Origin
koptekst:
- Geeft het domein van de site die het verzoek indient.
- Is vereist en moet afwijken van de host.
Algemene headers
Request URL: https://cors1.azurewebsites.net/api/values
Request Method: GET
Status Code: 200 OK
Antwoordheaders
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
Verzoekheaders
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
aanvragen stelt de server de header AntwoordheadersAccess-Control-Allow-Origin: {allowed origin}
in het antwoord in. Het geïmplementeerde voorbeeld, knopaanvraag OPTIONS
Verwijderen, bevat bijvoorbeeld de volgende headers:
Algemene headers
Request URL: https://cors3.azurewebsites.net/api/TodoItems2/MyDelete2/5
Request Method: OPTIONS
Status Code: 204 No Content
Antwoordheaders
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
Verzoekheaders
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 de voorgaande antwoordheaders stelt de server in het antwoord de header Access-Control-Allow-Origin in. De https://cors1.azurewebsites.net
waarde van deze header komt overeen met de Origin
header van de aanvraag.
Als AllowAnyOrigin wordt aangeroepen, wordt de Access-Control-Allow-Origin: *
, de jokertekenwaarde, geretourneerd.
AllowAnyOrigin
staat elke oorsprong toe.
Als het antwoord de header niet bevat Access-Control-Allow-Origin
, mislukt de cross-origin-aanvraag. De browser staat de aanvraag met name niet toe. Zelfs als de server een geslaagd antwoord retourneert, maakt de browser het antwoord niet beschikbaar voor de client-app.
OPTIES-aanvragen weergeven
Standaard worden in de browsers Chrome en Edge geen OPTIES-aanvragen weergegeven op het netwerktabblad van de F12-hulpprogramma's. OPTIES-aanvragen weergeven in deze browsers:
-
chrome://flags/#out-of-blink-cors
ofedge://flags/#out-of-blink-cors
- schakel de vlag uit.
- herstarten.
In Firefox worden OPTIES-aanvragen standaard weergegeven.
CORS in IIS
Bij de implementatie in IIS moet CORS worden uitgevoerd vóór Windows-verificatie als de server niet is geconfigureerd om anonieme toegang toe te staan. Ter ondersteuning van dit scenario moet de IIS CORS-module worden geïnstalleerd en geconfigureerd voor de app.
CORS testen
Het voorbeelddownload bevat code om CORS te testen. Zie hoe ukunt downloaden. Het voorbeeld is een API-project met Razor Pages toegevoegd:
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();
});
}
}
Waarschuwing
WithOrigins("https://localhost:<port>");
mag alleen worden gebruikt voor het testen van een voorbeeld-app die vergelijkbaar is met de voorbeeldcode voor het downloaden.
ValuesController
Hieronder vindt u de eindpunten voor het testen:
[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 wordt geleverd door het Rick.Docs.Samples.RouteInfo NuGet-pakket en toont routegegevens.
Test de voorgaande voorbeeldcode met behulp van een van de volgende methoden:
- Voer het voorbeeld uit met
dotnet run
behulp van de standaard-URL vanhttps://localhost:5001
. - Voer het voorbeeld uit vanuit Visual Studio met de poort ingesteld op 44398 voor een URL van
https://localhost:44398
.
Een browser gebruiken met de F12-hulpprogramma's:
Selecteer de knop Waarden en controleer de kopteksten op het tabblad Netwerk .
Selecteer de PUT-test knop. Zie WeergaveOPTIES-aanvragen voor instructies over het weergeven van de OPTIONS-aanvraag. De PUT-test maakt twee aanvragen, een OPTIONS preflight-aanvraag en een PUT-aanvraag.
Selecteer de
GetValues2 [DisableCors]
knop om een mislukte CORS-aanvraag te activeren. Zoals vermeld in het document, retourneert het antwoord 200 succes, maar wordt het CORS-verzoek niet gedaan. Selecteer het tabblad Console om de CORS-fout weer te geven. Afhankelijk van de browser wordt een fout weergegeven die lijkt op het volgende:Toegang voor het ophalen van
'https://cors1.azurewebsites.net/api/values/GetValues2'
vanaf oorsprong'https://cors3.azurewebsites.net'
is geblokkeerd door het CORS-beleid: Er is geen 'Access-Control-Allow-Origin' header aanwezig op de aangevraagde resource. Als een ondoorzichtig antwoord aan uw behoeften voldoet, stelt u de modus van de aanvraag in op 'no-cors' om de resource op te halen waarvoor CORS is uitgeschakeld.
CORS-eindpunten kunnen worden getest met een hulpprogramma, zoals curl of Fiddler. Wanneer u een hulpprogramma gebruikt, moet de oorsprong van de aanvraag die is opgegeven door de Origin
header verschillen van de host die de aanvraag ontvangt. Als de aanvraag niet cross-origin is op basis van de waarde van de Origin
header:
- Cors Middleware is niet nodig om de aanvraag te verwerken.
- CORS-headers worden niet geretourneerd in het antwoord.
Met de volgende opdracht curl
wordt een OPTIONS-aanvraag met informatie verzonden:
curl -X OPTIONS https://cors3.azurewebsites.net/api/TodoItems2/5 -i
CORS testen met eindpuntroutering en [HttpOptions]
Het inschakelen van CORS per eindpunt RequireCors
ondersteunt momenteel geen automatische preflight-aanvragen. Houd rekening met de volgende code die gebruikmaakt van eindpuntroutering om CORS in te schakelen:
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();
});
}
}
TodoItems1Controller
Hieronder vindt u eindpunten voor het testen:
[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);
}
Test de voorgaande code vanaf de testpagina (https://cors1.azurewebsites.net/test?number=1
) van het geïmplementeerde voorbeeld.
De knoppen Delete [EnableCors] en GET [EnableCors] slagen, omdat de eindpunten [EnableCors]
hebben voor preflight-aanvragen en daarop reageren. De andere eindpunten mislukken. De get-knop mislukt, omdat javaScript het volgende verzendt:
headers: {
"Content-Type": "x-custom-header"
},
Het volgende TodoItems2Controller
biedt vergelijkbare eindpunten, maar bevat expliciete code om te reageren op OPTIONS-aanvragen:
[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);
}
De voorgaande code kan worden getest door het voorbeeld te implementeren in Azure.In de vervolgkeuzelijst Controller , preflight te selecteren en vervolgens Controller in te stellen. Alle CORS-aanroepen naar de TodoItems2Controller
eindpunten zijn geslaagd.