Povolení žádostí mezi zdroji (CORS) v ASP.NET Core
Poznámka:
Toto není nejnovější verze tohoto článku. Aktuální verzi najdete v tomto článku ve verzi .NET 9.
Upozorňující
Tato verze ASP.NET Core se už nepodporuje. Další informace najdete v zásadách podpory .NET a .NET Core. Aktuální verzi najdete v tomto článku ve verzi .NET 9.
Důležité
Tyto informace se týkají předběžného vydání produktu, který může být podstatně změněn před komerčním vydáním. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.
Aktuální verzi najdete v tomto článku ve verzi .NET 9.
Autoři: Rick Anderson a Kirk Larkin
Tento článek ukazuje, jak je c ross-O rigin Resource Sharing (CORS) povolen v aplikaci ASP.NET Core.
Zabezpečení prohlížeče zabraňuje tomu, aby webová stránka odesílala požadavky do jiné domény, než je ta, která webovou stránku obsluhuje. Toto omezení se označuje jako zásada stejného zdroje. Zásada stejného zdroje brání škodlivým webům ve čtení citlivých dat z jiných webů. Někdy může být vhodné povolit jiným webům, aby vaše aplikace zpřístupňovala žádosti mezi zdroji. Další informace naleznete v článku Mozilla CORS.
Sdílení prostředků mezi zdroji (CORS):
- Je standard W3C, který umožňuje serveru uvolnit zásady stejného původu.
- Není to funkce zabezpečení, CORS uvolní zabezpečení. Rozhraní API není bezpečnější tím, že umožňuje CORS. Další informace najdete v tématu Jak CORS funguje.
- Umožňuje serveru explicitně povolit některé požadavky mezi zdroji a zároveň odmítnout jiné.
- Je bezpečnější a flexibilnější než dřívější techniky, jako je JSONP.
Zobrazení nebo stažení ukázkového kódu (postup stažení)
Stejný původ
Dvě adresy URL mají stejný původ, pokud mají stejná schémata, hostitele a porty (RFC 6454).
Tyto dvě adresy URL mají stejný původ:
https://example.com/foo.html
https://example.com/bar.html
Tyto adresy URL mají jiný původ než předchozí dvě adresy URL:
https://example.net
: Jiná doménahttps://contoso.example.com/foo.html
: Jiná subdoménahttp://example.com/foo.html
: Jiné schémahttps://example.com:9000/foo.html
: Jiný port
Povolení CORS
CORS můžete povolit třemi způsoby:
- V middlewaru pomocí pojmenované zásady nebo výchozí zásady.
- Pomocí směrování koncového bodu.
- S atributem [EnableCors]
Použití atributu [EnableCors] s pojmenovanou zásadou poskytuje nejlepší kontrolu v omezení koncových bodů, které podporují CORS.
Upozorňující
UseCors musí být volána ve správném pořadí. Další informace naleznete v tématu Pořadí middlewaru. UseCors
Například musí být volána před UseResponseCaching použitím UseResponseCaching
.
Každý přístup je podrobně popsaný v následujících částech.
CORS s pojmenovanými zásadami a middlewarem
Middleware CORS zpracovává požadavky mezi zdroji. Následující kód použije zásadu CORS pro všechny koncové body aplikace se zadanými zdroji:
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();
Předchozí kód:
- Nastaví název zásady na
_myAllowSpecificOrigins
. Název zásady je libovolný. - Volá metodu UseCors rozšíření a určuje
_myAllowSpecificOrigins
zásady CORS.UseCors
přidá middleware CORS. HovorUseCors
musí být umístěn zaUseRouting
, ale předUseAuthorization
. Další informace naleznete v tématu Pořadí middlewaru. - Volání AddCors pomocí výrazu lambda Lambda přebírá CorsPolicyBuilder objekt. Možnosti konfigurace, například
WithOrigins
, jsou popsány dále v tomto článku. - Povolí zásadu
_myAllowSpecificOrigins
CORS pro všechny koncové body kontroleru. Podívejte se na směrování koncových bodů, abyste použili zásadu CORS na konkrétní koncové body. - Při použití middlewaru pro ukládání odpovědí do mezipaměti zavolejte UseCors před UseResponseCaching.
Se směrováním koncového bodu musí být middleware CORS nakonfigurovaný tak, aby se prováděl mezi voláními a UseRouting
UseEndpoints
.
Volání AddCors metody přidá služby CORS do kontejneru služby aplikace:
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();
Další informace najdete v tématu Možnosti zásad CORS v tomto dokumentu.
Metody CorsPolicyBuilder mohou být zřetězený, jak je znázorněno v následujícím kódu:
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();
Poznámka: Zadaná adresa URL nesmí obsahovat koncové lomítko (/
). Pokud se /
adresa URL ukončí, vrátí se porovnání false
a nevrátí se žádná hlavička.
Pořadí UseCors a UseStaticFiles
Obvykle se UseStaticFiles
volá před UseCors
. Aplikace, které používají JavaScript k načtení statických souborů mezi weby, musí před voláním UseStaticFiles
volat UseCors
.
CORS s výchozími zásadami a middlewarem
Následující zvýrazněný kód povolí výchozí zásady CORS:
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();
Předchozí kód použije výchozí zásady CORS pro všechny koncové body kontroleru.
Povolení Cors se směrováním koncových bodů
Pomocí směrování koncového bodu je možné CORS povolit pro jednotlivé koncové body pomocí RequireCors sady rozšiřujících metod:
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();
V předchozím kódu:
app.UseCors
povolí middleware CORS. Vzhledem k tomu, že se nenakonfigurovala výchozí zásada,app.UseCors()
samotná možnost CORS nepovoluje.- Koncové
/echo
body kontroleru umožňují požadavky mezi zdroji pomocí zadaných zásad. - Koncové
/echo2
body stránky Razor neumožňují požadavky mezi zdroji, protože nebyly zadány žádné výchozí zásady.
Atribut [DisableCors] nezakazuje CORS, které bylo povoleno směrováním koncového bodu s RequireCors
.
Pokyny k testování kódu podobného předchozímu kódu najdete v části Test CORS s atributem [EnableCors] a metodou RequireCors.
Povolení CORS s atributy
Povolení CORS pomocí atributu [EnableCors] a použití pojmenované zásady pouze na koncové body, které vyžadují CORS, poskytuje nejlepší kontrolu.
Atribut [EnableCors] poskytuje alternativu k použití CORS globálně. Tento [EnableCors]
atribut umožňuje CORS pro vybrané koncové body, nikoli pro všechny koncové body:
[EnableCors]
určuje výchozí zásadu.[EnableCors("{Policy String}")]
určuje pojmenovanou zásadu.
Atribut [EnableCors]
lze použít na:
- Razor Stránka
PageModel
- Ovladač
- Metoda akce kontroleru
U kontrolerů, modelů stránek nebo metod akcí s atributem [EnableCors]
je možné použít různé zásady. [EnableCors]
Když se atribut použije u kontroleru, modelu stránky nebo metody akce a CORS je v middlewaru povolený, použijí se obě zásady. Doporučujeme kombinovat zásady. Pomocí tlačítka[EnableCors]
atribut nebo middleware, ne oba ve stejné aplikaci.
Následující kód použije pro každou metodu jinou zásadu:
[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(),
};
}
}
Následující kód vytvoří dvě zásady CORS:
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();
Nejlepší kontrolu nad omezováním požadavků CORS:
- Používá se
[EnableCors("MyPolicy")]
s pojmenovanými zásadami. - Nedefinujte výchozí zásadu.
- Nepoužívejte směrování koncového bodu.
Kód v další části odpovídá předchozímu seznamu.
Zakázání CORS
Atribut [DisableCors] nezakazuje CORS, které bylo povoleno směrováním koncového bodu.
Následující kód definuje zásadu "MyPolicy"
CORS:
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();
Následující kód zakáže CORS pro GetValues2
akci:
[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();
}
Předchozí kód:
- Nepovoluje CORS se směrováním koncových bodů.
- Nedefinuje výchozí zásady CORS.
- Pomocí funkce [EnableCors("MyPolicy")] povolí
"MyPolicy"
zásady CORS pro kontroler. - Zakáže CORS pro metodu
GetValues2
.
Pokyny k testování předchozího kódu najdete v části Test CORS .
Možnosti zásad CORS
Tato část popisuje různé možnosti, které je možné nastavit v zásadách CORS:
- Nastavení povolených zdrojů
- Nastavení povolených metod HTTP
- Nastavení hlaviček povolených požadavků
- Nastavení vystavených hlaviček odpovědí
- Přihlašovací údaje v požadavcích mezi zdroji
- Nastavení doby předběžného vypršení platnosti
AddPolicy je volána v Program.cs
. U některých možností může být užitečné nejprve přečíst část Jak CORS funguje .
Nastavení povolených zdrojů
AllowAnyOrigin: Umožňuje CORS požadavky ze všech původů s jakýmkoli schématem (http
nebo https
). AllowAnyOrigin
je nezabezpečený, protože každý web může do aplikace vyhovět žádostem mezi zdroji.
Poznámka:
AllowAnyOrigin
Určení a AllowCredentials
je nezabezpečená konfigurace a může vést k padělání požadavků mezi weby. Služba CORS vrátí neplatnou odpověď CORS, když je aplikace nakonfigurovaná s oběma metodami.
AllowAnyOrigin
ovlivňuje předběžné požadavky a hlavičku Access-Control-Allow-Origin
. Další informace najdete v části Předběžné požadavky .
SetIsOriginAllowedToAllowWildcardSubdomains: Nastaví IsOriginAllowed vlastnost zásady na funkci, která umožňuje, aby zdroje odpovídaly nakonfigurované zástupné doméně při vyhodnocování, zda je původ povolený.
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();
Nastavení povolených metod HTTP
- Povoluje libovolnou metodu HTTP:
- Ovlivňuje předběžné požadavky a hlavičku
Access-Control-Allow-Methods
. Další informace najdete v části Předběžné požadavky .
Nastavení hlaviček povolených požadavků
Pokud chcete povolit odesílání konkrétních hlaviček v požadavku CORS, označované jako hlavičky žádosti autora, volání WithHeaders a zadání povolených hlaviček:
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();
Pokud chcete povolit všechna záhlaví žádosti autora, zavolejte AllowAnyHeader:
var MyAllowSpecificOrigins = "_MyAllowSubdomainPolicy";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("https://*.example.com")
.AllowAnyHeader();
});
});
builder.Services.AddControllers();
var app = builder.Build();
AllowAnyHeader
ovlivňuje předběžné požadavky a hlavičku Hlavičky žádostí o přístup. Další informace najdete v části Předběžné požadavky .
Zásady middlewaru CORS odpovídají konkrétním hlavičkám určeným WithHeaders
pouze tehdy, když hlavičky odeslané přesně Access-Control-Request-Headers
odpovídají hlavičkám uvedeným v WithHeaders
.
Představte si například aplikaci nakonfigurovanou takto:
app.UseCors(policy => policy.WithHeaders(HeaderNames.CacheControl));
Middleware CORS odmítne předběžný požadavek s následující hlavičkou požadavku, protože Content-Language
(HeaderNames.ContentLanguage) není uvedený v WithHeaders
:
Access-Control-Request-Headers: Cache-Control, Content-Language
Aplikace vrátí odpověď 200 OK , ale neodesílá hlavičky CORS zpět. Prohlížeč se proto nepokouší o požadavek mezi zdroji.
Nastavení vystavených hlaviček odpovědí
Ve výchozím nastavení prohlížeč nezpřístupňuje do aplikace všechny hlavičky odpovědi. Další informace najdete v tématu Sdílení prostředků mezi zdroji W3C (terminologie): Jednoduchá hlavička odpovědi.
Hlavičky odpovědi, které jsou ve výchozím nastavení k dispozici, jsou:
Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma
Specifikace CORS volá tyto hlavičky jednoduchých hlaviček odpovědi. Pokud chcete aplikaci zpřístupnit další hlavičky, zavolejte WithExposedHeaders:
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();
Přihlašovací údaje v požadavcích mezi zdroji
Přihlašovací údaje vyžadují speciální zpracování v požadavku CORS. Ve výchozím nastavení prohlížeč neodesílá přihlašovací údaje s požadavkem mezi zdroji. Přihlašovací údaje zahrnují soubory cookie a schémata ověřování HTTP. Chcete-li odeslat přihlašovací údaje s žádostí mezi zdroji, musí klient nastavit XMLHttpRequest.withCredentials
na true
hodnotu .
Přímé použití XMLHttpRequest
:
var xhr = new XMLHttpRequest();
xhr.open('get', 'https://www.example.com/api/test');
xhr.withCredentials = true;
Pomocí jQuery:
$.ajax({
type: 'get',
url: 'https://www.example.com/api/test',
xhrFields: {
withCredentials: true
}
});
Použití rozhraní Fetch API:
fetch('https://www.example.com/api/test', {
credentials: 'include'
});
Server musí přihlašovací údaje povolit. Pokud chcete povolit přihlašovací údaje mezi zdroji, zavolejte AllowCredentials:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MyMyAllowCredentialsPolicy",
policy =>
{
policy.WithOrigins("http://example.com")
.AllowCredentials();
});
});
builder.Services.AddControllers();
var app = builder.Build();
Odpověď HTTP obsahuje hlavičku Access-Control-Allow-Credentials
, která prohlížeči říká, že server povoluje přihlašovací údaje pro požadavek mezi zdroji.
Pokud prohlížeč odešle přihlašovací údaje, ale odpověď neobsahuje platnou Access-Control-Allow-Credentials
hlavičku, prohlížeč nezobrazí odpověď aplikaci a požadavek mezi zdroji selže.
Povolení přihlašovacích údajů mezi zdroji představuje bezpečnostní riziko. Web v jiné doméně může odeslat přihlašovací údaje přihlášeného uživatele do aplikace jménem uživatele bez vědomí uživatele.
Specifikace CORS také uvádí, že nastavení původu na "*"
(všechny zdroje) je neplatné, pokud je hlavička Access-Control-Allow-Credentials
přítomna.
Předběžné požadavky
U některých požadavků CORS prohlížeč před provedením skutečného požadavku odešle další požadavek OPTIONS . Tento požadavek se nazývá předběžný požadavek. Prohlížeč může předběžný požadavek přeskočit, pokud jsou splněny všechny následující podmínky:
- Metoda požadavku je GET, HEAD nebo POST.
- Aplikace nenastavuje jiné hlavičky požadavků než
Accept
,Accept-Language
,Content-Language
, ,Content-Type
neboLast-Event-ID
. - Hlavička
Content-Type
, pokud je nastavená, má jednu z následujících hodnot:application/x-www-form-urlencoded
multipart/form-data
text/plain
Pravidlo hlavičky požadavku nastavené pro požadavek klienta se vztahuje na hlavičky, které aplikace nastaví voláním setRequestHeader
objektu XMLHttpRequest
. Specifikace CORS volá hlavičky požadavku autora. Pravidlo se nevztahuje na hlavičky, které může prohlížeč nastavit, například User-Agent
, Host
nebo Content-Length
.
Poznámka:
Tento článek obsahuje adresy URL vytvořené nasazením ukázkového kódu na dva weby https://cors3.azurewebsites.net
Azure a https://cors.azurewebsites.net
.
Následuje příklad odpovědi podobné předběžnému požadavku vytvořenému z tlačítka [Put test] v části Test CORS tohoto dokumentu.
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
Předběžný požadavek používá metodu HTTP OPTIONS . Může obsahovat následující hlavičky:
- Access-Control-Request-Method: Metoda HTTP, která se použije pro skutečný požadavek.
- Hlavičky žádostí řízení přístupu: Seznam hlaviček požadavků, které aplikace nastaví na skutečný požadavek. Jak jsme uvedli dříve, nezahrnuje hlavičky, které prohlížeče nastaví, například
User-Agent
.
Pokud je předběžný požadavek odepřen, aplikace vrátí 200 OK
odpověď, ale nenastaví hlavičky CORS. Prohlížeč se proto nepokouší o požadavek mezi zdroji. Příklad odepřené předběžné žádosti najdete v části Testovací CORS tohoto dokumentu.
Pomocí nástrojů F12 konzolová aplikace zobrazí v závislosti na prohlížeči chybu podobnou jedné z následujících možností:
- Firefox: Blokovaný požadavek mezi zdroji: Stejné zásady původu nepovolují čtení vzdáleného prostředku na adrese
https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5
. (Důvod: Požadavek CORS nebyl úspěšný). Další informace - Chromium: Zásady CORS zablokovaly přístup k načtení nahttps://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5 "' z původu'https://cors3.azurewebsites.net: Odpověď na předběžný požadavek neprojde kontrolou řízení přístupu: U požadovaného prostředku není k dispozici žádná hlavička Access-Control-Allow-Origin. Pokud vaše potřeby obsluhují neprůspatnou odpověď, nastavte režim požadavku na no-cors, aby se načítal prostředek se zakázaným CORS.
Pokud chcete povolit konkrétní záhlaví, zavolejte 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();
Pokud chcete povolit všechna záhlaví žádosti autora, zavolejte AllowAnyHeader:
using Microsoft.Net.Http.Headers;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MyAllowAllHeadersPolicy",
policy =>
{
policy.WithOrigins("https://*.example.com")
.AllowAnyHeader();
});
});
builder.Services.AddControllers();
var app = builder.Build();
Prohlížeče nejsou konzistentní ve způsobu jejich nastavení Access-Control-Request-Headers
. Pokud máte některou z těchto:
- Záhlaví jsou nastavená na cokoli jiného než
"*"
- AllowAnyHeader je volána: Zahrňte alespoň
Accept
,Content-Type
a , aOrigin
navíc všechny vlastní hlavičky, které chcete podporovat.
Automatický předletový kód požadavku
Při použití zásad CORS:
- Globálně voláním
app.UseCors
Program.cs
. - Použití atributu
[EnableCors]
ASP.NET Core reaguje na předběžný požadavek OPTIONS.
Toto chování ukazuje část Test CORS tohoto dokumentu.
Atribut [HttpOptions] pro předběžné požadavky
Když je CORS povolená s příslušnými zásadami, ASP.NET Core obvykle automaticky reaguje na předběžné požadavky CORS.
Následující kód používá atribut [HttpOptions] k vytvoření koncových bodů pro požadavky OPTIONS:
[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);
}
Pokyny k testování předchozího kódu najdete v části Test CORS s atributem [EnableCors] a metodou RequireCors.
Nastavení doby předběžného vypršení platnosti
Hlavička Access-Control-Max-Age
určuje, jak dlouho může být odpověď na předběžný požadavek uložena do mezipaměti. Chcete-li nastavit toto záhlaví, zavolejte SetPreflightMaxAge:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MySetPreflightExpirationPolicy",
policy =>
{
policy.WithOrigins("http://example.com")
.SetPreflightMaxAge(TimeSpan.FromSeconds(2520));
});
});
builder.Services.AddControllers();
var app = builder.Build();
Povolení CORS v koncovém bodu
Jak CORS funguje
Tato část popisuje, co se stane v požadavku CORS na úrovni zpráv HTTP.
- CORS není funkce zabezpečení. CORS je standard W3C, který umožňuje serveru uvolnit zásady stejného původu.
- Například herec se zlými úmysly může na vašem webu použít skriptování mezi weby (XSS) a provést žádost mezi weby s podporou CORS k krádeži informací.
- Rozhraní API není bezpečnější tím, že umožňuje CORS.
- Je na klientovi (prohlížeči) a vynucuje CORS. Server spustí požadavek a vrátí odpověď. Je to klient, který vrací chybu a blokuje odpověď. Například některý z následujících nástrojů zobrazí odpověď serveru:
- Fiddler
- .NET HttpClient
- Webový prohlížeč zadáním adresy URL do adresního řádku.
- Je na klientovi (prohlížeči) a vynucuje CORS. Server spustí požadavek a vrátí odpověď. Je to klient, který vrací chybu a blokuje odpověď. Například některý z následujících nástrojů zobrazí odpověď serveru:
- Je to způsob, jak serveru umožnit prohlížečům spouštět požadavek XHR nebo Fetch API mezi zdroji, které by jinak bylo zakázáno.
- Prohlížeče bez CORS nemůžou provádět žádosti mezi zdroji. Před CORS se k obejití tohoto omezení použil JSONP . JSONP nepoužívá XHR, k přijetí odpovědi používá
<script>
značku. Skripty je možné načíst mezi zdroji.
- Prohlížeče bez CORS nemůžou provádět žádosti mezi zdroji. Před CORS se k obejití tohoto omezení použil JSONP . JSONP nepoužívá XHR, k přijetí odpovědi používá
Specifikace CORS zavedla několik nových hlaviček HTTP, které umožňují požadavky mezi zdroji. Pokud prohlížeč podporuje CORS, nastaví tato záhlaví automaticky pro žádosti mezi zdroji. K povolení CORS se nevyžaduje vlastní javascriptový kód.
Následuje příklad požadavku mezi zdroji z tlačítka Test hodnot do https://cors1.azurewebsites.net/api/values
. Hlavička Origin
:
- Poskytuje doménu lokality, která požadavek provádí.
- Vyžaduje se a musí se lišit od hostitele.
Obecné hlavičky
Request URL: https://cors1.azurewebsites.net/api/values
Request Method: GET
Status Code: 200 OK
Hlavičky odpovědi
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
Hlavičky požadavku
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 ...
V OPTIONS
požadavcích server nastaví hlavičku hlavičky Access-Control-Allow-Origin: {allowed origin}
odpovědi v odpovědi. Například v ukázkovém kódu Delete [EnableCors]
obsahuje požadavek na tlačítko OPTIONS
následující hlavičky:
Obecné hlavičky
Request URL: https://cors3.azurewebsites.net/api/TodoItems2/MyDelete2/5
Request Method: OPTIONS
Status Code: 204 No Content
Hlavičky odpovědi
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
Hlavičky požadavku
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
V předchozích hlavičkách odpovědi server nastaví v odpovědi hlavičku Access-Control-Allow-Origin . Hodnota https://cors1.azurewebsites.net
této hlavičky odpovídá Origin
hlavičce požadavku.
Pokud AllowAnyOrigin je volána, Access-Control-Allow-Origin: *
vrátí se hodnota zástupné dokumentace. AllowAnyOrigin
umožňuje jakýkoli původ.
Pokud odpověď hlavičku Access-Control-Allow-Origin
neobsahuje, požadavek mezi zdroji selže. Konkrétně prohlížeč požadavek zakáže. I když server vrátí úspěšnou odpověď, prohlížeč nepřístupní odpověď klientské aplikaci.
Přesměrování HTTP na HTTPS způsobuje ERR_INVALID_REDIRECT předběžné žádosti CORS.
Požadavky na koncový bod pomocí protokolu HTTP, které jsou přesměrované na HTTPS, selžouUseHttpsRedirection.ERR_INVALID_REDIRECT on the CORS preflight request
Projekty rozhraní API můžou odmítnout požadavky HTTP místo toho UseHttpsRedirection
, aby přesměrovály požadavky na HTTPS.
CORS ve službě IIS
Při nasazování do služby IIS musí CORS běžet před ověřováním systému Windows, pokud server není nakonfigurovaný tak, aby povoloval anonymní přístup. Pro podporu tohoto scénáře je potřeba nainstalovat a nakonfigurovat modul CORS služby IIS pro aplikaci.
Testování CORS
Ukázkový soubor ke stažení obsahuje kód pro testování CORS. Podívejte se, jak si stáhnout. Ukázka je projekt rozhraní API s přidanými stránkami Razor :
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();
Upozorňující
WithOrigins("https://localhost:<port>");
by se měla použít pouze k testování ukázkové aplikace podobné ukázkového kódu ke stažení.
ValuesController
Následující body poskytují koncové body pro testování:
[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 poskytuje balíček NuGet Rick.Docs.Samples.RouteInfo a zobrazí informace o trase.
Otestujte předchozí vzorový kód pomocí jednoho z následujících přístupů:
- Spusťte ukázku s
dotnet run
použitím výchozí adresy URLhttps://localhost:5001
souboru . - Spusťte ukázku ze sady Visual Studio s portem nastaveným na 44398 pro adresu URL souboru
https://localhost:44398
.
Použití prohlížeče s nástroji F12:
Vyberte tlačítko Hodnoty a zkontrolujte záhlaví na kartě Síť.
Vyberte tlačítko TEST PUT. Pokyny k zobrazení požadavku OPTIONS najdete v části Zobrazení MOŽNOSTÍ . Test PUT vytvoří dva požadavky, předběžný požadavek OPTIONS a požadavek PUT.
GetValues2 [DisableCors]
Výběrem tlačítka aktivujte neúspěšný požadavek CORS. Jak je uvedeno v dokumentu, odpověď vrátí úspěch 200, ale požadavek CORS není proveden. Výběrem karty Konzola zobrazíte chybu CORS. V závislosti na prohlížeči se zobrazí chyba podobná této:Zásady CORS blokovaly přístup k načtení
'https://cors1.azurewebsites.net/api/values/GetValues2'
z zdroje'https://cors3.azurewebsites.net'
: U požadovaného prostředku není k dispozici žádná hlavička Access-Control-Allow-Origin. Pokud vaše potřeby obsluhují neprůspatnou odpověď, nastavte režim požadavku na no-cors, aby se načítal prostředek se zakázaným CORS.
Koncové body s podporou CORS je možné testovat pomocí nástroje, jako je curl nebo Fiddler. Při použití nástroje se původ požadavku určeného Origin
hlavičkou musí lišit od hostitele, který požadavek přijímá. Pokud požadavek není mezi zdroji založený na hodnotě hlavičky Origin
:
- Není nutné, aby middleware CORS zpracovával požadavek.
- Hlavičky CORS se v odpovědi nevracejí.
Následující příkaz používá curl
k vydání požadavku OPTIONS s informacemi:
curl -X OPTIONS https://cors3.azurewebsites.net/api/TodoItems2/5 -i
Testování CORS s atributem [EnableCors] a metodou RequireCors
Zvažte následující kód, který používá směrování koncových bodů k povolení CORS na základě jednotlivých koncových bodů pomocí 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();
Všimněte si, že pouze /echo
koncový bod používá RequireCors
k povolení požadavků mezi zdroji pomocí zadané zásady. Následující kontrolery povolují CORS pomocí atributu [EnableCors].
TodoItems1Controller
Následující body poskytují koncové body pro testování:
[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);
}
Tlačítka Delete [EnableCors] a GET [EnableCors] jsou úspěšná, protože koncové body mají [EnableCors]
a reagují na předběžné požadavky. Ostatní koncové body selžou. Tlačítko GET selže, protože JavaScript odesílá:
headers: {
"Content-Type": "x-custom-header"
},
TodoItems2Controller
Následující body poskytují podobné koncové body, ale obsahují explicitní kód pro reakci na požadavky OPTIONS:
[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);
}
Předchozí kód je možné otestovat nasazením ukázky do Azure. V rozevíracím seznamu Kontroler vyberte Předlet a pak Nastavte kontroler. Všechna volání CORS do TodoItems2Controller
koncových bodů jsou úspěšná.
Další materiály
Autoři: Rick Anderson a Kirk Larkin
Tento článek ukazuje, jak povolit CORS v aplikaci ASP.NET Core.
Zabezpečení prohlížeče zabraňuje tomu, aby webová stránka odesílala požadavky do jiné domény, než je ta, která webovou stránku obsluhuje. Toto omezení se označuje jako zásada stejného zdroje. Zásada stejného zdroje brání škodlivým webům ve čtení citlivých dat z jiných webů. Někdy může být vhodné povolit jiným webům, aby vaše aplikace zpřístupňovala žádosti mezi zdroji. Další informace naleznete v článku Mozilla CORS.
Sdílení prostředků mezi zdroji (CORS):
- Je standard W3C, který umožňuje serveru uvolnit zásady stejného původu.
- Není to funkce zabezpečení, CORS uvolní zabezpečení. Rozhraní API není bezpečnější tím, že umožňuje CORS. Další informace najdete v tématu Jak CORS funguje.
- Umožňuje serveru explicitně povolit některé požadavky mezi zdroji a zároveň odmítnout jiné.
- Je bezpečnější a flexibilnější než dřívější techniky, jako je JSONP.
Zobrazení nebo stažení ukázkového kódu (postup stažení)
Stejný původ
Dvě adresy URL mají stejný původ, pokud mají stejná schémata, hostitele a porty (RFC 6454).
Tyto dvě adresy URL mají stejný původ:
https://example.com/foo.html
https://example.com/bar.html
Tyto adresy URL mají jiný původ než předchozí dvě adresy URL:
https://example.net
: Jiná doménahttps://www.example.com/foo.html
: Jiná subdoménahttp://example.com/foo.html
: Jiné schémahttps://example.com:9000/foo.html
: Jiný port
Povolení CORS
CORS můžete povolit třemi způsoby:
- V middlewaru pomocí pojmenované zásady nebo výchozí zásady.
- Pomocí směrování koncového bodu.
- S atributem [EnableCors]
Použití atributu [EnableCors] s pojmenovanou zásadou poskytuje nejlepší kontrolu v omezení koncových bodů, které podporují CORS.
Upozorňující
UseCors musí být volána ve správném pořadí. Další informace naleznete v tématu Pořadí middlewaru. UseCors
Například musí být volána před UseResponseCaching použitím UseResponseCaching
.
Každý přístup je podrobně popsaný v následujících částech.
CORS s pojmenovanými zásadami a middlewarem
Middleware CORS zpracovává požadavky mezi zdroji. Následující kód použije zásadu CORS pro všechny koncové body aplikace se zadanými zdroji:
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();
Předchozí kód:
- Nastaví název zásady na
_myAllowSpecificOrigins
. Název zásady je libovolný. - Volá metodu UseCors rozšíření a určuje
_myAllowSpecificOrigins
zásady CORS.UseCors
přidá middleware CORS. HovorUseCors
musí být umístěn zaUseRouting
, ale předUseAuthorization
. Další informace naleznete v tématu Pořadí middlewaru. - Volání AddCors pomocí výrazu lambda Lambda přebírá CorsPolicyBuilder objekt. Možnosti konfigurace, například
WithOrigins
, jsou popsány dále v tomto článku. - Povolí zásadu
_myAllowSpecificOrigins
CORS pro všechny koncové body kontroleru. Podívejte se na směrování koncových bodů, abyste použili zásadu CORS na konkrétní koncové body. - Při použití middlewaru pro ukládání odpovědí do mezipaměti zavolejte UseCors před UseResponseCaching.
Se směrováním koncového bodu musí být middleware CORS nakonfigurovaný tak, aby se prováděl mezi voláními a UseRouting
UseEndpoints
.
Volání AddCors metody přidá služby CORS do kontejneru služby aplikace:
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();
Další informace najdete v tématu Možnosti zásad CORS v tomto dokumentu.
Metody CorsPolicyBuilder mohou být zřetězený, jak je znázorněno v následujícím kódu:
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();
Poznámka: Zadaná adresa URL nesmí obsahovat koncové lomítko (/
). Pokud se /
adresa URL ukončí, vrátí se porovnání false
a nevrátí se žádná hlavička.
Upozorňující
UseCors
musí být umístěn za UseRouting
a před UseAuthorization
. To zajistí, aby hlavičky CORS byly zahrnuty do odpovědi pro autorizovaná i neautorizovaná volání.
Pořadí UseCors a UseStaticFiles
Obvykle se UseStaticFiles
volá před UseCors
. Aplikace, které používají JavaScript k načtení statických souborů mezi weby, musí před voláním UseStaticFiles
volat UseCors
.
CORS s výchozími zásadami a middlewarem
Následující zvýrazněný kód povolí výchozí zásady CORS:
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();
Předchozí kód použije výchozí zásady CORS pro všechny koncové body kontroleru.
Povolení Cors se směrováním koncových bodů
Pomocí směrování koncového bodu je možné CORS povolit pro jednotlivé koncové body pomocí RequireCors sady rozšiřujících metod:
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();
V předchozím kódu:
app.UseCors
povolí middleware CORS. Vzhledem k tomu, že se nenakonfigurovala výchozí zásada,app.UseCors()
samotná možnost CORS nepovoluje.- Koncové
/echo
body kontroleru umožňují požadavky mezi zdroji pomocí zadaných zásad. - Koncové
/echo2
body stránky Razor neumožňují požadavky mezi zdroji, protože nebyly zadány žádné výchozí zásady.
Atribut [DisableCors] nezakazuje CORS, které bylo povoleno směrováním koncového bodu s RequireCors
.
V ASP.NET Core 7.0 [EnableCors]
musí atribut předat parametr nebo ASP0023 Upozornění se vygeneruje z nejednoznačné shody na trase. ASP.NET Core 8.0 a novější negeneruje ASP0023
upozornění.
[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);
}
Pokyny k testování kódu podobného předchozímu kódu najdete v části Test CORS s atributem [EnableCors] a metodou RequireCors.
Povolení CORS s atributy
Povolení CORS pomocí atributu [EnableCors] a použití pojmenované zásady pouze na koncové body, které vyžadují CORS, poskytuje nejlepší kontrolu.
Atribut [EnableCors] poskytuje alternativu k použití CORS globálně. Tento [EnableCors]
atribut umožňuje CORS pro vybrané koncové body, nikoli pro všechny koncové body:
[EnableCors]
určuje výchozí zásadu.[EnableCors("{Policy String}")]
určuje pojmenovanou zásadu.
Atribut [EnableCors]
lze použít na:
- Razor Stránka
PageModel
- Ovladač
- Metoda akce kontroleru
U kontrolerů, modelů stránek nebo metod akcí s atributem [EnableCors]
je možné použít různé zásady. [EnableCors]
Když se atribut použije u kontroleru, modelu stránky nebo metody akce a CORS je v middlewaru povolený, použijí se obě zásady. Doporučujeme kombinovat zásady. Pomocí tlačítka[EnableCors]
atribut nebo middleware, ne oba ve stejné aplikaci.
Následující kód použije pro každou metodu jinou zásadu:
[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(),
};
}
}
Následující kód vytvoří dvě zásady CORS:
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();
Nejlepší kontrolu nad omezováním požadavků CORS:
- Používá se
[EnableCors("MyPolicy")]
s pojmenovanými zásadami. - Nedefinujte výchozí zásadu.
- Nepoužívejte směrování koncového bodu.
Kód v další části odpovídá předchozímu seznamu.
Zakázání CORS
Atribut [DisableCors] nezakazuje CORS, které bylo povoleno směrováním koncového bodu.
Následující kód definuje zásadu "MyPolicy"
CORS:
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();
Následující kód zakáže CORS pro GetValues2
akci:
[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();
}
Předchozí kód:
- Nepovoluje CORS se směrováním koncových bodů.
- Nedefinuje výchozí zásady CORS.
- Pomocí funkce [EnableCors("MyPolicy")] povolí
"MyPolicy"
zásady CORS pro kontroler. - Zakáže CORS pro metodu
GetValues2
.
Pokyny k testování předchozího kódu najdete v části Test CORS .
Možnosti zásad CORS
Tato část popisuje různé možnosti, které je možné nastavit v zásadách CORS:
- Nastavení povolených zdrojů
- Nastavení povolených metod HTTP
- Nastavení hlaviček povolených požadavků
- Nastavení vystavených hlaviček odpovědí
- Přihlašovací údaje v požadavcích mezi zdroji
- Nastavení doby předběžného vypršení platnosti
AddPolicy je volána v Program.cs
. U některých možností může být užitečné nejprve přečíst část Jak CORS funguje .
Nastavení povolených zdrojů
AllowAnyOrigin: Umožňuje CORS požadavky ze všech původů s jakýmkoli schématem (http
nebo https
). AllowAnyOrigin
je nezabezpečený, protože každý web může do aplikace vyhovět žádostem mezi zdroji.
Poznámka:
AllowAnyOrigin
Určení a AllowCredentials
je nezabezpečená konfigurace a může vést k padělání požadavků mezi weby. Služba CORS vrátí neplatnou odpověď CORS, když je aplikace nakonfigurovaná s oběma metodami.
AllowAnyOrigin
ovlivňuje předběžné požadavky a hlavičku Access-Control-Allow-Origin
. Další informace najdete v části Předběžné požadavky .
SetIsOriginAllowedToAllowWildcardSubdomains: Nastaví IsOriginAllowed vlastnost zásady na funkci, která umožňuje, aby zdroje odpovídaly nakonfigurované zástupné doméně při vyhodnocování, zda je původ povolený.
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();
Nastavení povolených metod HTTP
- Povoluje libovolnou metodu HTTP:
- Ovlivňuje předběžné požadavky a hlavičku
Access-Control-Allow-Methods
. Další informace najdete v části Předběžné požadavky .
Nastavení hlaviček povolených požadavků
Pokud chcete povolit odesílání konkrétních hlaviček v požadavku CORS, označované jako hlavičky žádosti autora, volání WithHeaders a zadání povolených hlaviček:
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();
Pokud chcete povolit všechna záhlaví žádosti autora, zavolejte AllowAnyHeader:
var MyAllowSpecificOrigins = "_MyAllowSubdomainPolicy";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("https://*.example.com")
.AllowAnyHeader();
});
});
builder.Services.AddControllers();
var app = builder.Build();
AllowAnyHeader
ovlivňuje předběžné požadavky a hlavičku Hlavičky žádostí o přístup. Další informace najdete v části Předběžné požadavky .
Zásady middlewaru CORS odpovídají konkrétním hlavičkám určeným WithHeaders
pouze tehdy, když hlavičky odeslané přesně Access-Control-Request-Headers
odpovídají hlavičkám uvedeným v WithHeaders
.
Představte si například aplikaci nakonfigurovanou takto:
app.UseCors(policy => policy.WithHeaders(HeaderNames.CacheControl));
Middleware CORS odmítne předběžný požadavek s následující hlavičkou požadavku, protože Content-Language
(HeaderNames.ContentLanguage) není uvedený v WithHeaders
:
Access-Control-Request-Headers: Cache-Control, Content-Language
Aplikace vrátí odpověď 200 OK , ale neodesílá hlavičky CORS zpět. Prohlížeč se proto nepokouší o požadavek mezi zdroji.
Nastavení vystavených hlaviček odpovědí
Ve výchozím nastavení prohlížeč nezpřístupňuje do aplikace všechny hlavičky odpovědi. Další informace najdete v tématu Sdílení prostředků mezi zdroji W3C (terminologie): Jednoduchá hlavička odpovědi.
Hlavičky odpovědi, které jsou ve výchozím nastavení k dispozici, jsou:
Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma
Specifikace CORS volá tyto hlavičky jednoduchých hlaviček odpovědi. Pokud chcete aplikaci zpřístupnit další hlavičky, zavolejte WithExposedHeaders:
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();
Přihlašovací údaje v požadavcích mezi zdroji
Přihlašovací údaje vyžadují speciální zpracování v požadavku CORS. Ve výchozím nastavení prohlížeč neodesílá přihlašovací údaje s požadavkem mezi zdroji. Přihlašovací údaje zahrnují soubory cookie a schémata ověřování HTTP. Chcete-li odeslat přihlašovací údaje s žádostí mezi zdroji, musí klient nastavit XMLHttpRequest.withCredentials
na true
hodnotu .
Přímé použití XMLHttpRequest
:
var xhr = new XMLHttpRequest();
xhr.open('get', 'https://www.example.com/api/test');
xhr.withCredentials = true;
Pomocí jQuery:
$.ajax({
type: 'get',
url: 'https://www.example.com/api/test',
xhrFields: {
withCredentials: true
}
});
Použití rozhraní Fetch API:
fetch('https://www.example.com/api/test', {
credentials: 'include'
});
Server musí přihlašovací údaje povolit. Pokud chcete povolit přihlašovací údaje mezi zdroji, zavolejte AllowCredentials:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MyMyAllowCredentialsPolicy",
policy =>
{
policy.WithOrigins("http://example.com")
.AllowCredentials();
});
});
builder.Services.AddControllers();
var app = builder.Build();
Odpověď HTTP obsahuje hlavičku Access-Control-Allow-Credentials
, která prohlížeči říká, že server povoluje přihlašovací údaje pro požadavek mezi zdroji.
Pokud prohlížeč odešle přihlašovací údaje, ale odpověď neobsahuje platnou Access-Control-Allow-Credentials
hlavičku, prohlížeč nezobrazí odpověď aplikaci a požadavek mezi zdroji selže.
Povolení přihlašovacích údajů mezi zdroji představuje bezpečnostní riziko. Web v jiné doméně může odeslat přihlašovací údaje přihlášeného uživatele do aplikace jménem uživatele bez vědomí uživatele.
Specifikace CORS také uvádí, že nastavení původu na "*"
(všechny zdroje) je neplatné, pokud je hlavička Access-Control-Allow-Credentials
přítomna.
Předběžné požadavky
U některých požadavků CORS prohlížeč před provedením skutečného požadavku odešle další požadavek OPTIONS . Tento požadavek se nazývá předběžný požadavek. Prohlížeč může předběžný požadavek přeskočit, pokud jsou splněny všechny následující podmínky:
- Metoda požadavku je GET, HEAD nebo POST.
- Aplikace nenastavuje jiné hlavičky požadavků než
Accept
,Accept-Language
,Content-Language
, ,Content-Type
neboLast-Event-ID
. - Hlavička
Content-Type
, pokud je nastavená, má jednu z následujících hodnot:application/x-www-form-urlencoded
multipart/form-data
text/plain
Pravidlo hlavičky požadavku nastavené pro požadavek klienta se vztahuje na hlavičky, které aplikace nastaví voláním setRequestHeader
objektu XMLHttpRequest
. Specifikace CORS volá hlavičky požadavku autora. Pravidlo se nevztahuje na hlavičky, které může prohlížeč nastavit, například User-Agent
, Host
nebo Content-Length
.
Následuje příklad odpovědi podobné předběžnému požadavku vytvořenému z tlačítka [Put test] v části Test CORS tohoto dokumentu.
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
Předběžný požadavek používá metodu HTTP OPTIONS . Může obsahovat následující hlavičky:
- Access-Control-Request-Method: Metoda HTTP, která se použije pro skutečný požadavek.
- Hlavičky žádostí řízení přístupu: Seznam hlaviček požadavků, které aplikace nastaví na skutečný požadavek. Jak jsme uvedli dříve, nezahrnuje hlavičky, které prohlížeče nastaví, například
User-Agent
. - Metody Allow-Access-Control-Allow
Pokud je předběžný požadavek odepřen, aplikace vrátí 200 OK
odpověď, ale nenastaví hlavičky CORS. Prohlížeč se proto nepokouší o požadavek mezi zdroji. Příklad odepřené předběžné žádosti najdete v části Testovací CORS tohoto dokumentu.
Pomocí nástrojů F12 konzolová aplikace zobrazí v závislosti na prohlížeči chybu podobnou jedné z následujících možností:
- Firefox: Blokovaný požadavek mezi zdroji: Stejné zásady původu nepovolují čtení vzdáleného prostředku na adrese
https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5
. (Důvod: Požadavek CORS nebyl úspěšný). Další informace - Chromium: Zásady CORS zablokovaly přístup k načtení nahttps://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5 "' z původu'https://cors3.azurewebsites.net: Odpověď na předběžný požadavek neprojde kontrolou řízení přístupu: U požadovaného prostředku není k dispozici žádná hlavička Access-Control-Allow-Origin. Pokud vaše potřeby obsluhují neprůspatnou odpověď, nastavte režim požadavku na no-cors, aby se načítal prostředek se zakázaným CORS.
Pokud chcete povolit konkrétní záhlaví, zavolejte 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();
Pokud chcete povolit všechna záhlaví žádosti autora, zavolejte AllowAnyHeader:
using Microsoft.Net.Http.Headers;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MyAllowAllHeadersPolicy",
policy =>
{
policy.WithOrigins("https://*.example.com")
.AllowAnyHeader();
});
});
builder.Services.AddControllers();
var app = builder.Build();
Prohlížeče nejsou konzistentní ve způsobu jejich nastavení Access-Control-Request-Headers
. Pokud máte některou z těchto:
- Záhlaví jsou nastavená na cokoli jiného než
"*"
- AllowAnyHeader je volána: Zahrňte alespoň
Accept
,Content-Type
a , aOrigin
navíc všechny vlastní hlavičky, které chcete podporovat.
Automatický předletový kód požadavku
Při použití zásad CORS:
- Globálně voláním
app.UseCors
Program.cs
. - Použití atributu
[EnableCors]
ASP.NET Core reaguje na předběžný požadavek OPTIONS.
Toto chování ukazuje část Test CORS tohoto dokumentu.
Atribut [HttpOptions] pro předběžné požadavky
Když je CORS povolená s příslušnými zásadami, ASP.NET Core obvykle automaticky reaguje na předběžné požadavky CORS.
Následující kód používá atribut [HttpOptions] k vytvoření koncových bodů pro požadavky OPTIONS:
[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);
}
Pokyny k testování předchozího kódu najdete v části Test CORS s atributem [EnableCors] a metodou RequireCors.
Nastavení doby předběžného vypršení platnosti
Hlavička Access-Control-Max-Age
určuje, jak dlouho může být odpověď na předběžný požadavek uložena do mezipaměti. Chcete-li nastavit toto záhlaví, zavolejte SetPreflightMaxAge:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MySetPreflightExpirationPolicy",
policy =>
{
policy.WithOrigins("http://example.com")
.SetPreflightMaxAge(TimeSpan.FromSeconds(2520));
});
});
builder.Services.AddControllers();
var app = builder.Build();
Povolení CORS v koncovém bodu
Jak CORS funguje
Tato část popisuje, co se stane v požadavku CORS na úrovni zpráv HTTP.
- CORS není funkce zabezpečení. CORS je standard W3C, který umožňuje serveru uvolnit zásady stejného původu.
- Například herec se zlými úmysly může na vašem webu použít skriptování mezi weby (XSS) a provést žádost mezi weby s podporou CORS k krádeži informací.
- Rozhraní API není bezpečnější tím, že umožňuje CORS.
- Je na klientovi (prohlížeči) a vynucuje CORS. Server spustí požadavek a vrátí odpověď. Je to klient, který vrací chybu a blokuje odpověď. Například některý z následujících nástrojů zobrazí odpověď serveru:
- Fiddler
- .NET HttpClient
- Webový prohlížeč zadáním adresy URL do adresního řádku.
- Je na klientovi (prohlížeči) a vynucuje CORS. Server spustí požadavek a vrátí odpověď. Je to klient, který vrací chybu a blokuje odpověď. Například některý z následujících nástrojů zobrazí odpověď serveru:
- Je to způsob, jak serveru umožnit prohlížečům spouštět požadavek XHR nebo Fetch API mezi zdroji, které by jinak bylo zakázáno.
- Prohlížeče bez CORS nemůžou provádět žádosti mezi zdroji. Před CORS se k obejití tohoto omezení použil JSONP . JSONP nepoužívá XHR, k přijetí odpovědi používá
<script>
značku. Skripty je možné načíst mezi zdroji.
- Prohlížeče bez CORS nemůžou provádět žádosti mezi zdroji. Před CORS se k obejití tohoto omezení použil JSONP . JSONP nepoužívá XHR, k přijetí odpovědi používá
Specifikace CORS zavedla několik nových hlaviček HTTP, které umožňují požadavky mezi zdroji. Pokud prohlížeč podporuje CORS, nastaví tato záhlaví automaticky pro žádosti mezi zdroji. K povolení CORS se nevyžaduje vlastní javascriptový kód.
V nasazené ukázce vyberte tlačítko PUT test.
Hlavička Origin
:
- Poskytuje doménu lokality, která požadavek provádí.
- Vyžaduje se a musí se lišit od hostitele.
Obecné hlavičky
Request URL: https://cors1.azurewebsites.net/api/values
Request Method: GET
Status Code: 200 OK
Hlavičky odpovědi
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
Hlavičky požadavku
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 ...
V OPTIONS
požadavcích server nastaví hlavičku hlavičky Access-Control-Allow-Origin: {allowed origin}
odpovědi v odpovědi. Například v ukázkovém kódu Delete [EnableCors]
obsahuje požadavek na tlačítko OPTIONS
následující hlavičky:
Obecné hlavičky
Request URL: https://cors3.azurewebsites.net/api/TodoItems2/MyDelete2/5
Request Method: OPTIONS
Status Code: 204 No Content
Hlavičky odpovědi
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
Hlavičky požadavku
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
V předchozích hlavičkách odpovědi server nastaví v odpovědi hlavičku Access-Control-Allow-Origin . Hodnota https://cors1.azurewebsites.net
této hlavičky odpovídá Origin
hlavičce požadavku.
Pokud AllowAnyOrigin je volána, Access-Control-Allow-Origin: *
vrátí se hodnota zástupné dokumentace. AllowAnyOrigin
umožňuje jakýkoli původ.
Pokud odpověď hlavičku Access-Control-Allow-Origin
neobsahuje, požadavek mezi zdroji selže. Konkrétně prohlížeč požadavek zakáže. I když server vrátí úspěšnou odpověď, prohlížeč nepřístupní odpověď klientské aplikaci.
Přesměrování HTTP na HTTPS způsobuje ERR_INVALID_REDIRECT předběžné žádosti CORS.
Požadavky na koncový bod pomocí protokolu HTTP, které jsou přesměrované na HTTPS, selžouUseHttpsRedirection.ERR_INVALID_REDIRECT on the CORS preflight request
Projekty rozhraní API můžou odmítnout požadavky HTTP místo toho UseHttpsRedirection
, aby přesměrovály požadavky na HTTPS.
CORS ve službě IIS
Při nasazování do služby IIS musí CORS běžet před ověřováním systému Windows, pokud server není nakonfigurovaný tak, aby povoloval anonymní přístup. Pro podporu tohoto scénáře je potřeba nainstalovat a nakonfigurovat modul CORS služby IIS pro aplikaci.
Testování CORS
Ukázkový soubor ke stažení obsahuje kód pro testování CORS. Podívejte se, jak si stáhnout. Ukázka je projekt rozhraní API s přidanými stránkami Razor :
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();
Upozorňující
WithOrigins("https://localhost:<port>");
by se měla použít pouze k testování ukázkové aplikace podobné ukázkového kódu ke stažení.
ValuesController
Následující body poskytují koncové body pro testování:
[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 poskytuje balíček NuGet Rick.Docs.Samples.RouteInfo a zobrazí informace o trase.
Otestujte předchozí vzorový kód pomocí jednoho z následujících přístupů:
- Spusťte ukázku s
dotnet run
použitím výchozí adresy URLhttps://localhost:5001
souboru . - Spusťte ukázku ze sady Visual Studio s portem nastaveným na 44398 pro adresu URL souboru
https://localhost:44398
.
Použití prohlížeče s nástroji F12:
Vyberte tlačítko Hodnoty a zkontrolujte záhlaví na kartě Síť.
Vyberte tlačítko TEST PUT. Pokyny k zobrazení požadavku OPTIONS najdete v části Zobrazení MOŽNOSTÍ . Test PUT vytvoří dva požadavky, předběžný požadavek OPTIONS a požadavek PUT.
GetValues2 [DisableCors]
Výběrem tlačítka aktivujte neúspěšný požadavek CORS. Jak je uvedeno v dokumentu, odpověď vrátí úspěch 200, ale požadavek CORS není proveden. Výběrem karty Konzola zobrazíte chybu CORS. V závislosti na prohlížeči se zobrazí chyba podobná této:Zásady CORS blokovaly přístup k načtení
'https://cors1.azurewebsites.net/api/values/GetValues2'
z zdroje'https://cors3.azurewebsites.net'
: U požadovaného prostředku není k dispozici žádná hlavička Access-Control-Allow-Origin. Pokud vaše potřeby obsluhují neprůspatnou odpověď, nastavte režim požadavku na no-cors, aby se načítal prostředek se zakázaným CORS.
Koncové body s podporou CORS je možné testovat pomocí nástroje, jako je curl nebo Fiddler. Při použití nástroje se původ požadavku určeného Origin
hlavičkou musí lišit od hostitele, který požadavek přijímá. Pokud požadavek není mezi zdroji založený na hodnotě hlavičky Origin
:
- Není nutné, aby middleware CORS zpracovával požadavek.
- Hlavičky CORS se v odpovědi nevracejí.
Následující příkaz používá curl
k vydání požadavku OPTIONS s informacemi:
curl -X OPTIONS https://cors3.azurewebsites.net/api/TodoItems2/5 -i
Testování CORS s atributem [EnableCors] a metodou RequireCors
Zvažte následující kód, který používá směrování koncových bodů k povolení CORS na základě jednotlivých koncových bodů pomocí 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();
Všimněte si, že pouze /echo
koncový bod používá RequireCors
k povolení požadavků mezi zdroji pomocí zadané zásady. Následující kontrolery povolují CORS pomocí atributu [EnableCors].
TodoItems1Controller
Následující body poskytují koncové body pro testování:
[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);
}
Tlačítka Delete [EnableCors] a GET [EnableCors] jsou úspěšná, protože koncové body mají [EnableCors]
a reagují na předběžné požadavky. Ostatní koncové body selžou. Tlačítko GET selže, protože JavaScript odesílá:
headers: {
"Content-Type": "x-custom-header"
},
TodoItems2Controller
Následující body poskytují podobné koncové body, ale obsahují explicitní kód pro reakci na požadavky OPTIONS:
[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);
}
Předchozí kód je možné otestovat nasazením ukázky do Azure.In rozevíracího seznamu Kontroleru , výběrem možnosti Preflight a následným nastavením kontroleru. Všechna volání CORS do TodoItems2Controller
koncových bodů jsou úspěšná.
Další materiály
Autoři: Rick Anderson a Kirk Larkin
Tento článek ukazuje, jak povolit CORS v aplikaci ASP.NET Core.
Zabezpečení prohlížeče zabraňuje tomu, aby webová stránka odesílala požadavky do jiné domény, než je ta, která webovou stránku obsluhuje. Toto omezení se označuje jako zásada stejného zdroje. Zásada stejného zdroje brání škodlivým webům ve čtení citlivých dat z jiných webů. Někdy může být vhodné povolit jiným webům, aby vaše aplikace zpřístupňovala žádosti mezi zdroji. Další informace naleznete v článku Mozilla CORS.
Sdílení prostředků mezi zdroji (CORS):
- Je standard W3C, který umožňuje serveru uvolnit zásady stejného původu.
- Není to funkce zabezpečení, CORS uvolní zabezpečení. Rozhraní API není bezpečnější tím, že umožňuje CORS. Další informace najdete v tématu Jak CORS funguje.
- Umožňuje serveru explicitně povolit některé požadavky mezi zdroji a zároveň odmítnout jiné.
- Je bezpečnější a flexibilnější než dřívější techniky, jako je JSONP.
Zobrazení nebo stažení ukázkového kódu (postup stažení)
Stejný původ
Dvě adresy URL mají stejný původ, pokud mají stejná schémata, hostitele a porty (RFC 6454).
Tyto dvě adresy URL mají stejný původ:
https://example.com/foo.html
https://example.com/bar.html
Tyto adresy URL mají jiný původ než předchozí dvě adresy URL:
https://example.net
: Jiná doménahttps://www.example.com/foo.html
: Jiná subdoménahttp://example.com/foo.html
: Jiné schémahttps://example.com:9000/foo.html
: Jiný port
Povolení CORS
CORS můžete povolit třemi způsoby:
- V middlewaru pomocí pojmenované zásady nebo výchozí zásady.
- Pomocí směrování koncového bodu.
- S atributem [EnableCors]
Použití atributu [EnableCors] s pojmenovanou zásadou poskytuje nejlepší kontrolu v omezení koncových bodů, které podporují CORS.
Upozorňující
UseCors musí být volána ve správném pořadí. Další informace naleznete v tématu Pořadí middlewaru. UseCors
Například musí být volána před UseResponseCaching použitím UseResponseCaching
.
Každý přístup je podrobně popsaný v následujících částech.
CORS s pojmenovanými zásadami a middlewarem
Middleware CORS zpracovává požadavky mezi zdroji. Následující kód použije zásadu CORS pro všechny koncové body aplikace se zadanými zdroji:
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();
Předchozí kód:
- Nastaví název zásady na
_myAllowSpecificOrigins
. Název zásady je libovolný. - Volá metodu UseCors rozšíření a určuje
_myAllowSpecificOrigins
zásady CORS.UseCors
přidá middleware CORS. HovorUseCors
musí být umístěn zaUseRouting
, ale předUseAuthorization
. Další informace naleznete v tématu Pořadí middlewaru. - Volání AddCors pomocí výrazu lambda Lambda přebírá CorsPolicyBuilder objekt. Možnosti konfigurace, například
WithOrigins
, jsou popsány dále v tomto článku. - Povolí zásadu
_myAllowSpecificOrigins
CORS pro všechny koncové body kontroleru. Podívejte se na směrování koncových bodů, abyste použili zásadu CORS na konkrétní koncové body. - Při použití middlewaru pro ukládání odpovědí do mezipaměti zavolejte UseCors před UseResponseCaching.
Se směrováním koncového bodu musí být middleware CORS nakonfigurovaný tak, aby se prováděl mezi voláními a UseRouting
UseEndpoints
.
Volání AddCors metody přidá služby CORS do kontejneru služby aplikace:
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();
Další informace najdete v tématu Možnosti zásad CORS v tomto dokumentu.
Metody CorsPolicyBuilder mohou být zřetězený, jak je znázorněno v následujícím kódu:
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();
Poznámka: Zadaná adresa URL nesmí obsahovat koncové lomítko (/
). Pokud se /
adresa URL ukončí, vrátí se porovnání false
a nevrátí se žádná hlavička.
Upozorňující
UseCors
musí být umístěn za UseRouting
a před UseAuthorization
. To zajistí, aby hlavičky CORS byly zahrnuty do odpovědi pro autorizovaná i neautorizovaná volání.
Pořadí UseCors a UseStaticFiles
Obvykle se UseStaticFiles
volá před UseCors
. Aplikace, které používají JavaScript k načtení statických souborů mezi weby, musí před voláním UseStaticFiles
volat UseCors
.
CORS s výchozími zásadami a middlewarem
Následující zvýrazněný kód povolí výchozí zásady CORS:
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();
Předchozí kód použije výchozí zásady CORS pro všechny koncové body kontroleru.
Povolení Cors se směrováním koncových bodů
Povolení CORS na základě RequireCors
jednotlivých koncových bodů nepodporuje automatické předběžné požadavky. Další informace najdete v tomto problému na GitHubu a otestování CORS se směrováním koncových bodů a [HttpOptions].
Pomocí směrování koncového bodu je možné CORS povolit pro jednotlivé koncové body pomocí RequireCors sady rozšiřujících metod:
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();
V předchozím kódu:
app.UseCors
povolí middleware CORS. Vzhledem k tomu, že se nenakonfigurovala výchozí zásada,app.UseCors()
samotná možnost CORS nepovoluje.- Koncové
/echo
body kontroleru umožňují požadavky mezi zdroji pomocí zadaných zásad. - Koncové
/echo2
body stránky Razor neumožňují požadavky mezi zdroji, protože nebyly zadány žádné výchozí zásady.
Atribut [DisableCors] nezakazuje CORS, které bylo povoleno směrováním koncového bodu s RequireCors
.
Povolení CORS s atributy
Povolení CORS pomocí atributu [EnableCors] a použití pojmenované zásady pouze na koncové body, které vyžadují CORS, poskytuje nejlepší kontrolu.
Atribut [EnableCors] poskytuje alternativu k použití CORS globálně. Tento [EnableCors]
atribut umožňuje CORS pro vybrané koncové body, nikoli pro všechny koncové body:
[EnableCors]
určuje výchozí zásadu.[EnableCors("{Policy String}")]
určuje pojmenovanou zásadu.
Atribut [EnableCors]
lze použít na:
- Razor Stránka
PageModel
- Ovladač
- Metoda akce kontroleru
U kontrolerů, modelů stránek nebo metod akcí s atributem [EnableCors]
je možné použít různé zásady. [EnableCors]
Když se atribut použije u kontroleru, modelu stránky nebo metody akce a CORS je v middlewaru povolený, použijí se obě zásady. Doporučujeme kombinovat zásady. Pomocí tlačítka[EnableCors]
atribut nebo middleware, ne oba ve stejné aplikaci.
Následující kód použije pro každou metodu jinou zásadu:
[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(),
};
}
}
Následující kód vytvoří dvě zásady CORS:
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();
Nejlepší kontrolu nad omezováním požadavků CORS:
- Používá se
[EnableCors("MyPolicy")]
s pojmenovanými zásadami. - Nedefinujte výchozí zásadu.
- Nepoužívejte směrování koncového bodu.
Kód v další části odpovídá předchozímu seznamu.
Zakázání CORS
Atribut [DisableCors] nezakazuje CORS, které bylo povoleno směrováním koncového bodu.
Následující kód definuje zásadu "MyPolicy"
CORS:
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();
Následující kód zakáže CORS pro GetValues2
akci:
[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();
}
Předchozí kód:
- Nepovoluje CORS se směrováním koncových bodů.
- Nedefinuje výchozí zásady CORS.
- Pomocí funkce [EnableCors("MyPolicy")] povolí
"MyPolicy"
zásady CORS pro kontroler. - Zakáže CORS pro metodu
GetValues2
.
Pokyny k testování předchozího kódu najdete v části Test CORS .
Možnosti zásad CORS
Tato část popisuje různé možnosti, které je možné nastavit v zásadách CORS:
- Nastavení povolených zdrojů
- Nastavení povolených metod HTTP
- Nastavení hlaviček povolených požadavků
- Nastavení vystavených hlaviček odpovědí
- Přihlašovací údaje v požadavcích mezi zdroji
- Nastavení doby předběžného vypršení platnosti
AddPolicy je volána v Program.cs
. U některých možností může být užitečné nejprve přečíst část Jak CORS funguje .
Nastavení povolených zdrojů
AllowAnyOrigin: Umožňuje CORS požadavky ze všech původů s jakýmkoli schématem (http
nebo https
). AllowAnyOrigin
je nezabezpečený, protože každý web může do aplikace vyhovět žádostem mezi zdroji.
Poznámka:
AllowAnyOrigin
Určení a AllowCredentials
je nezabezpečená konfigurace a může vést k padělání požadavků mezi weby. Služba CORS vrátí neplatnou odpověď CORS, když je aplikace nakonfigurovaná s oběma metodami.
AllowAnyOrigin
ovlivňuje předběžné požadavky a hlavičku Access-Control-Allow-Origin
. Další informace najdete v části Předběžné požadavky .
SetIsOriginAllowedToAllowWildcardSubdomains: Nastaví IsOriginAllowed vlastnost zásady na funkci, která umožňuje, aby zdroje odpovídaly nakonfigurované zástupné doméně při vyhodnocování, zda je původ povolený.
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();
Nastavení povolených metod HTTP
- Povoluje libovolnou metodu HTTP:
- Ovlivňuje předběžné požadavky a hlavičku
Access-Control-Allow-Methods
. Další informace najdete v části Předběžné požadavky .
Nastavení hlaviček povolených požadavků
Pokud chcete povolit odesílání konkrétních hlaviček v požadavku CORS, označované jako hlavičky žádosti autora, volání WithHeaders a zadání povolených hlaviček:
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();
Pokud chcete povolit všechna záhlaví žádosti autora, zavolejte AllowAnyHeader:
var MyAllowSpecificOrigins = "_MyAllowSubdomainPolicy";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("https://*.example.com")
.AllowAnyHeader();
});
});
builder.Services.AddControllers();
var app = builder.Build();
AllowAnyHeader
ovlivňuje předběžné požadavky a hlavičku Hlavičky žádostí o přístup. Další informace najdete v části Předběžné požadavky .
Zásady middlewaru CORS odpovídají konkrétním hlavičkám určeným WithHeaders
pouze tehdy, když hlavičky odeslané přesně Access-Control-Request-Headers
odpovídají hlavičkám uvedeným v WithHeaders
.
Představte si například aplikaci nakonfigurovanou takto:
app.UseCors(policy => policy.WithHeaders(HeaderNames.CacheControl));
Middleware CORS odmítne předběžný požadavek s následující hlavičkou požadavku, protože Content-Language
(HeaderNames.ContentLanguage) není uvedený v WithHeaders
:
Access-Control-Request-Headers: Cache-Control, Content-Language
Aplikace vrátí odpověď 200 OK , ale neodesílá hlavičky CORS zpět. Prohlížeč se proto nepokouší o požadavek mezi zdroji.
Nastavení vystavených hlaviček odpovědí
Ve výchozím nastavení prohlížeč nezpřístupňuje do aplikace všechny hlavičky odpovědi. Další informace najdete v tématu Sdílení prostředků mezi zdroji W3C (terminologie): Jednoduchá hlavička odpovědi.
Hlavičky odpovědi, které jsou ve výchozím nastavení k dispozici, jsou:
Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma
Specifikace CORS volá tyto hlavičky jednoduchých hlaviček odpovědi. Pokud chcete aplikaci zpřístupnit další hlavičky, zavolejte WithExposedHeaders:
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();
Přihlašovací údaje v požadavcích mezi zdroji
Přihlašovací údaje vyžadují speciální zpracování v požadavku CORS. Ve výchozím nastavení prohlížeč neodesílá přihlašovací údaje s požadavkem mezi zdroji. Přihlašovací údaje zahrnují soubory cookie a schémata ověřování HTTP. Chcete-li odeslat přihlašovací údaje s žádostí mezi zdroji, musí klient nastavit XMLHttpRequest.withCredentials
na true
hodnotu .
Přímé použití XMLHttpRequest
:
var xhr = new XMLHttpRequest();
xhr.open('get', 'https://www.example.com/api/test');
xhr.withCredentials = true;
Pomocí jQuery:
$.ajax({
type: 'get',
url: 'https://www.example.com/api/test',
xhrFields: {
withCredentials: true
}
});
Použití rozhraní Fetch API:
fetch('https://www.example.com/api/test', {
credentials: 'include'
});
Server musí přihlašovací údaje povolit. Pokud chcete povolit přihlašovací údaje mezi zdroji, zavolejte AllowCredentials:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MyMyAllowCredentialsPolicy",
policy =>
{
policy.WithOrigins("http://example.com")
.AllowCredentials();
});
});
builder.Services.AddControllers();
var app = builder.Build();
Odpověď HTTP obsahuje hlavičku Access-Control-Allow-Credentials
, která prohlížeči říká, že server povoluje přihlašovací údaje pro požadavek mezi zdroji.
Pokud prohlížeč odešle přihlašovací údaje, ale odpověď neobsahuje platnou Access-Control-Allow-Credentials
hlavičku, prohlížeč nezobrazí odpověď aplikaci a požadavek mezi zdroji selže.
Povolení přihlašovacích údajů mezi zdroji představuje bezpečnostní riziko. Web v jiné doméně může odeslat přihlašovací údaje přihlášeného uživatele do aplikace jménem uživatele bez vědomí uživatele.
Specifikace CORS také uvádí, že nastavení původu na "*"
(všechny zdroje) je neplatné, pokud je hlavička Access-Control-Allow-Credentials
přítomna.
Předběžné požadavky
U některých požadavků CORS prohlížeč před provedením skutečného požadavku odešle další požadavek OPTIONS . Tento požadavek se nazývá předběžný požadavek. Prohlížeč může předběžný požadavek přeskočit, pokud jsou splněny všechny následující podmínky:
- Metoda požadavku je GET, HEAD nebo POST.
- Aplikace nenastavuje jiné hlavičky požadavků než
Accept
,Accept-Language
,Content-Language
, ,Content-Type
neboLast-Event-ID
. - Hlavička
Content-Type
, pokud je nastavená, má jednu z následujících hodnot:application/x-www-form-urlencoded
multipart/form-data
text/plain
Pravidlo hlavičky požadavku nastavené pro požadavek klienta se vztahuje na hlavičky, které aplikace nastaví voláním setRequestHeader
objektu XMLHttpRequest
. Specifikace CORS volá hlavičky požadavku autora. Pravidlo se nevztahuje na hlavičky, které může prohlížeč nastavit, například User-Agent
, Host
nebo Content-Length
.
Následuje příklad odpovědi podobné předběžnému požadavku vytvořenému z tlačítka [Put test] v části Test CORS tohoto dokumentu.
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
Předběžný požadavek používá metodu HTTP OPTIONS . Může obsahovat následující hlavičky:
- Access-Control-Request-Method: Metoda HTTP, která se použije pro skutečný požadavek.
- Hlavičky žádostí řízení přístupu: Seznam hlaviček požadavků, které aplikace nastaví na skutečný požadavek. Jak jsme uvedli dříve, nezahrnuje hlavičky, které prohlížeče nastaví, například
User-Agent
. - Metody Allow-Access-Control-Allow
Pokud je předběžný požadavek odepřen, aplikace vrátí 200 OK
odpověď, ale nenastaví hlavičky CORS. Prohlížeč se proto nepokouší o požadavek mezi zdroji. Příklad odepřené předběžné žádosti najdete v části Testovací CORS tohoto dokumentu.
Pomocí nástrojů F12 konzolová aplikace zobrazí v závislosti na prohlížeči chybu podobnou jedné z následujících možností:
- Firefox: Blokovaný požadavek mezi zdroji: Stejné zásady původu nepovolují čtení vzdáleného prostředku na adrese
https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5
. (Důvod: Požadavek CORS nebyl úspěšný). Další informace - Chromium: Zásady CORS zablokovaly přístup k načtení nahttps://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5 "' z původu'https://cors3.azurewebsites.net: Odpověď na předběžný požadavek neprojde kontrolou řízení přístupu: U požadovaného prostředku není k dispozici žádná hlavička Access-Control-Allow-Origin. Pokud vaše potřeby obsluhují neprůspatnou odpověď, nastavte režim požadavku na no-cors, aby se načítal prostředek se zakázaným CORS.
Pokud chcete povolit konkrétní záhlaví, zavolejte 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();
Pokud chcete povolit všechna záhlaví žádosti autora, zavolejte AllowAnyHeader:
using Microsoft.Net.Http.Headers;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MyAllowAllHeadersPolicy",
policy =>
{
policy.WithOrigins("https://*.example.com")
.AllowAnyHeader();
});
});
builder.Services.AddControllers();
var app = builder.Build();
Prohlížeče nejsou konzistentní ve způsobu jejich nastavení Access-Control-Request-Headers
. Pokud máte některou z těchto:
- Záhlaví jsou nastavená na cokoli jiného než
"*"
- AllowAnyHeader je volána: Zahrňte alespoň
Accept
,Content-Type
a , aOrigin
navíc všechny vlastní hlavičky, které chcete podporovat.
Automatický předletový kód požadavku
Při použití zásad CORS:
- Globálně voláním
app.UseCors
Program.cs
. - Použití atributu
[EnableCors]
ASP.NET Core reaguje na předběžný požadavek OPTIONS.
Povolení CORS na základě jednotlivých koncových bodů v RequireCors
současné době nepodporuje automatické předběžné požadavky.
Toto chování ukazuje část Test CORS tohoto dokumentu.
Atribut [HttpOptions] pro předběžné požadavky
Když je CORS povolená s příslušnými zásadami, ASP.NET Core obvykle automaticky reaguje na předběžné požadavky CORS. V některých scénářích to nemusí být tento případ. Například použití CORS se směrováním koncových bodů.
Následující kód používá atribut [HttpOptions] k vytvoření koncových bodů pro požadavky OPTIONS:
[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);
}
Nastavení doby předběžného vypršení platnosti
Hlavička Access-Control-Max-Age
určuje, jak dlouho může být odpověď na předběžný požadavek uložena do mezipaměti. Chcete-li nastavit toto záhlaví, zavolejte SetPreflightMaxAge:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("MySetPreflightExpirationPolicy",
policy =>
{
policy.WithOrigins("http://example.com")
.SetPreflightMaxAge(TimeSpan.FromSeconds(2520));
});
});
builder.Services.AddControllers();
var app = builder.Build();
Jak CORS funguje
Tato část popisuje, co se stane v požadavku CORS na úrovni zpráv HTTP.
- CORS není funkce zabezpečení. CORS je standard W3C, který umožňuje serveru uvolnit zásady stejného původu.
- Například herec se zlými úmysly může na vašem webu použít skriptování mezi weby (XSS) a provést žádost mezi weby s podporou CORS k krádeži informací.
- Rozhraní API není bezpečnější tím, že umožňuje CORS.
- Je na klientovi (prohlížeči) a vynucuje CORS. Server spustí požadavek a vrátí odpověď. Je to klient, který vrací chybu a blokuje odpověď. Například některý z následujících nástrojů zobrazí odpověď serveru:
- Fiddler
- .NET HttpClient
- Webový prohlížeč zadáním adresy URL do adresního řádku.
- Je na klientovi (prohlížeči) a vynucuje CORS. Server spustí požadavek a vrátí odpověď. Je to klient, který vrací chybu a blokuje odpověď. Například některý z následujících nástrojů zobrazí odpověď serveru:
- Je to způsob, jak serveru umožnit prohlížečům spouštět požadavek XHR nebo Fetch API mezi zdroji, které by jinak bylo zakázáno.
- Prohlížeče bez CORS nemůžou provádět žádosti mezi zdroji. Před CORS se k obejití tohoto omezení použil JSONP . JSONP nepoužívá XHR, k přijetí odpovědi používá
<script>
značku. Skripty je možné načíst mezi zdroji.
- Prohlížeče bez CORS nemůžou provádět žádosti mezi zdroji. Před CORS se k obejití tohoto omezení použil JSONP . JSONP nepoužívá XHR, k přijetí odpovědi používá
Specifikace CORS zavedla několik nových hlaviček HTTP, které umožňují požadavky mezi zdroji. Pokud prohlížeč podporuje CORS, nastaví tato záhlaví automaticky pro žádosti mezi zdroji. K povolení CORS se nevyžaduje vlastní javascriptový kód.
Následuje příklad požadavku mezi zdroji z tlačítka Test hodnot do https://cors1.azurewebsites.net/api/values
. Hlavička Origin
:
- Poskytuje doménu lokality, která požadavek provádí.
- Vyžaduje se a musí se lišit od hostitele.
Obecné hlavičky
Request URL: https://cors1.azurewebsites.net/api/values
Request Method: GET
Status Code: 200 OK
Hlavičky odpovědi
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
Hlavičky požadavku
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 ...
V OPTIONS
požadavcích server nastaví hlavičku hlavičky Access-Control-Allow-Origin: {allowed origin}
odpovědi v odpovědi. Například nasazená ukázka obsahuje požadavek na tlačítko OPTIONS
Delete [EnableCors] následující hlavičky:
Obecné hlavičky
Request URL: https://cors3.azurewebsites.net/api/TodoItems2/MyDelete2/5
Request Method: OPTIONS
Status Code: 204 No Content
Hlavičky odpovědi
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
Hlavičky požadavku
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
V předchozích hlavičkách odpovědi server nastaví v odpovědi hlavičku Access-Control-Allow-Origin . Hodnota https://cors1.azurewebsites.net
této hlavičky odpovídá Origin
hlavičce požadavku.
Pokud AllowAnyOrigin je volána, Access-Control-Allow-Origin: *
vrátí se hodnota zástupné dokumentace. AllowAnyOrigin
umožňuje jakýkoli původ.
Pokud odpověď hlavičku Access-Control-Allow-Origin
neobsahuje, požadavek mezi zdroji selže. Konkrétně prohlížeč požadavek zakáže. I když server vrátí úspěšnou odpověď, prohlížeč nepřístupní odpověď klientské aplikaci.
Přesměrování HTTP na HTTPS způsobuje ERR_INVALID_REDIRECT předběžné žádosti CORS.
Požadavky na koncový bod pomocí protokolu HTTP, které jsou přesměrované na HTTPS, selžouUseHttpsRedirection.ERR_INVALID_REDIRECT on the CORS preflight request
Projekty rozhraní API můžou odmítnout požadavky HTTP místo toho UseHttpsRedirection
, aby přesměrovály požadavky na HTTPS.
Zobrazení požadavků OPTIONS
Ve výchozím nastavení prohlížeče Chrome a Edge nezobrazují požadavky OPTIONS na kartě sítě nástrojů F12. Zobrazení požadavků OPTIONS v těchto prohlížečích:
chrome://flags/#out-of-blink-cors
neboedge://flags/#out-of-blink-cors
- zakažte příznak.
- restartovat.
Firefox zobrazuje ve výchozím nastavení žádosti OPTIONS.
CORS ve službě IIS
Při nasazování do služby IIS musí CORS běžet před ověřováním systému Windows, pokud server není nakonfigurovaný tak, aby povoloval anonymní přístup. Pro podporu tohoto scénáře je potřeba nainstalovat a nakonfigurovat modul CORS služby IIS pro aplikaci.
Testování CORS
Ukázkový soubor ke stažení obsahuje kód pro testování CORS. Podívejte se, jak si stáhnout. Ukázka je projekt rozhraní API s přidanými stránkami Razor :
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();
Upozorňující
WithOrigins("https://localhost:<port>");
by se měla použít pouze k testování ukázkové aplikace podobné ukázkového kódu ke stažení.
ValuesController
Následující body poskytují koncové body pro testování:
[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 poskytuje balíček NuGet Rick.Docs.Samples.RouteInfo a zobrazí informace o trase.
Otestujte předchozí vzorový kód pomocí jednoho z následujících přístupů:
- Spusťte ukázku s
dotnet run
použitím výchozí adresy URLhttps://localhost:5001
souboru . - Spusťte ukázku ze sady Visual Studio s portem nastaveným na 44398 pro adresu URL souboru
https://localhost:44398
.
Použití prohlížeče s nástroji F12:
Vyberte tlačítko Hodnoty a zkontrolujte záhlaví na kartě Síť.
Vyberte tlačítko TEST PUT. Pokyny k zobrazení požadavku OPTIONS najdete v části Zobrazení MOŽNOSTÍ . Test PUT vytvoří dva požadavky, předběžný požadavek OPTIONS a požadavek PUT.
GetValues2 [DisableCors]
Výběrem tlačítka aktivujte neúspěšný požadavek CORS. Jak je uvedeno v dokumentu, odpověď vrátí úspěch 200, ale požadavek CORS není proveden. Výběrem karty Konzola zobrazíte chybu CORS. V závislosti na prohlížeči se zobrazí chyba podobná této:Zásady CORS blokovaly přístup k načtení
'https://cors1.azurewebsites.net/api/values/GetValues2'
z zdroje'https://cors3.azurewebsites.net'
: U požadovaného prostředku není k dispozici žádná hlavička Access-Control-Allow-Origin. Pokud vaše potřeby obsluhují neprůspatnou odpověď, nastavte režim požadavku na no-cors, aby se načítal prostředek se zakázaným CORS.
Koncové body s podporou CORS je možné testovat pomocí nástroje, jako je curl nebo Fiddler. Při použití nástroje se původ požadavku určeného Origin
hlavičkou musí lišit od hostitele, který požadavek přijímá. Pokud požadavek není mezi zdroji založený na hodnotě hlavičky Origin
:
- Není nutné, aby middleware CORS zpracovával požadavek.
- Hlavičky CORS se v odpovědi nevracejí.
Následující příkaz používá curl
k vydání požadavku OPTIONS s informacemi:
curl -X OPTIONS https://cors3.azurewebsites.net/api/TodoItems2/5 -i
Testování CORS se směrováním koncových bodů a [HttpOptions]
Povolení CORS na základě jednotlivých koncových bodů v RequireCors
současné době nepodporuje automatické předběžné požadavky. Zvažte následující kód, který používá směrování koncových bodů k povolení CORS:
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
Následující body poskytují koncové body pro testování:
[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);
}
Otestujte předchozí kód z testovací stránky (https://cors1.azurewebsites.net/test?number=1
) nasazené ukázky.
Tlačítka Delete [EnableCors] a GET [EnableCors] jsou úspěšná, protože koncové body mají [EnableCors]
a reagují na předběžné požadavky. Ostatní koncové body selžou. Tlačítko GET selže, protože JavaScript odesílá:
headers: {
"Content-Type": "x-custom-header"
},
TodoItems2Controller
Následující body poskytují podobné koncové body, ale obsahují explicitní kód pro reakci na požadavky OPTIONS:
[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);
}
Předchozí kód je možné otestovat nasazením ukázky do Azure.In rozevíracího seznamu Kontroleru , výběrem možnosti Preflight a následným nastavením kontroleru. Všechna volání CORS do TodoItems2Controller
koncových bodů jsou úspěšná.
Další materiály
Autoři: Rick Anderson a Kirk Larkin
Tento článek ukazuje, jak povolit CORS v aplikaci ASP.NET Core.
Zabezpečení prohlížeče zabraňuje tomu, aby webová stránka odesílala požadavky do jiné domény, než je ta, která webovou stránku obsluhuje. Toto omezení se označuje jako zásada stejného zdroje. Zásada stejného zdroje brání škodlivým webům ve čtení citlivých dat z jiných webů. Někdy může být vhodné povolit jiným webům, aby vaše aplikace zpřístupňovala žádosti mezi zdroji. Další informace naleznete v článku Mozilla CORS.
Sdílení prostředků mezi zdroji (CORS):
- Je standard W3C, který umožňuje serveru uvolnit zásady stejného původu.
- Není to funkce zabezpečení, CORS uvolní zabezpečení. Rozhraní API není bezpečnější tím, že umožňuje CORS. Další informace najdete v tématu Jak CORS funguje.
- Umožňuje serveru explicitně povolit některé požadavky mezi zdroji a zároveň odmítnout jiné.
- Je bezpečnější a flexibilnější než dřívější techniky, jako je JSONP.
Zobrazení nebo stažení ukázkového kódu (postup stažení)
Stejný původ
Dvě adresy URL mají stejný původ, pokud mají stejná schémata, hostitele a porty (RFC 6454).
Tyto dvě adresy URL mají stejný původ:
https://example.com/foo.html
https://example.com/bar.html
Tyto adresy URL mají jiný původ než předchozí dvě adresy URL:
https://example.net
: Jiná doménahttps://www.example.com/foo.html
: Jiná subdoménahttp://example.com/foo.html
: Jiné schémahttps://example.com:9000/foo.html
: Jiný port
Povolení CORS
CORS můžete povolit třemi způsoby:
- V middlewaru pomocí pojmenované zásady nebo výchozí zásady.
- Pomocí směrování koncového bodu.
- S atributem [EnableCors]
Použití atributu [EnableCors] s pojmenovanou zásadou poskytuje nejlepší kontrolu v omezení koncových bodů, které podporují CORS.
Upozorňující
UseCors musí být volána ve správném pořadí. Další informace naleznete v tématu Pořadí middlewaru. UseCors
Například musí být volána před UseResponseCaching použitím UseResponseCaching
.
Každý přístup je podrobně popsaný v následujících částech.
CORS s pojmenovanými zásadami a middlewarem
Middleware CORS zpracovává požadavky mezi zdroji. Následující kód použije zásadu CORS pro všechny koncové body aplikace se zadanými zdroji:
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();
});
}
}
Předchozí kód:
- Nastaví název zásady na
_myAllowSpecificOrigins
. Název zásady je libovolný. - Volá metodu UseCors rozšíření a určuje
_myAllowSpecificOrigins
zásady CORS.UseCors
přidá middleware CORS. HovorUseCors
musí být umístěn zaUseRouting
, ale předUseAuthorization
. Další informace naleznete v tématu Pořadí middlewaru. - Volání AddCors pomocí výrazu lambda Lambda přebírá CorsPolicyBuilder objekt. Možnosti konfigurace, například
WithOrigins
, jsou popsány dále v tomto článku. - Povolí zásadu
_myAllowSpecificOrigins
CORS pro všechny koncové body kontroleru. Podívejte se na směrování koncových bodů, abyste použili zásadu CORS na konkrétní koncové body. - Při použití middlewaru pro ukládání odpovědí do mezipaměti zavolejte UseCors před UseResponseCaching.
Se směrováním koncového bodu musí být middleware CORS nakonfigurovaný tak, aby se prováděl mezi voláními a UseRouting
UseEndpoints
.
Pokyny k testování kódu podobného předchozímu kódu najdete v části Test CORS .
Volání AddCors metody přidá služby CORS do kontejneru služby aplikace:
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();
}
Další informace najdete v tématu Možnosti zásad CORS v tomto dokumentu.
Metody CorsPolicyBuilder mohou být zřetězený, jak je znázorněno v následujícím kódu:
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();
}
Poznámka: Zadaná adresa URL nesmí obsahovat koncové lomítko (/
). Pokud se /
adresa URL ukončí, vrátí se porovnání false
a nevrátí se žádná hlavička.
CORS s výchozími zásadami a middlewarem
Následující zvýrazněný kód povolí výchozí zásady CORS:
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();
});
}
}
Předchozí kód použije výchozí zásady CORS pro všechny koncové body kontroleru.
Povolení Cors se směrováním koncových bodů
Povolení CORS na základě RequireCors
jednotlivých koncových bodů nepodporuje automatické předběžné požadavky. Další informace najdete v tomto problému na GitHubu a otestování CORS se směrováním koncových bodů a [HttpOptions].
Pomocí směrování koncového bodu je možné CORS povolit pro jednotlivé koncové body pomocí RequireCors sady rozšiřujících metod:
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();
});
}
}
V předchozím kódu:
app.UseCors
povolí middleware CORS. Vzhledem k tomu, že se nenakonfigurovala výchozí zásada,app.UseCors()
samotná možnost CORS nepovoluje.- Koncové
/echo
body kontroleru umožňují požadavky mezi zdroji pomocí zadaných zásad. - Koncové
/echo2
body stránky Razor neumožňují požadavky mezi zdroji, protože nebyly zadány žádné výchozí zásady.
Atribut [DisableCors] nezakazuje CORS, které bylo povoleno směrováním koncového bodu s RequireCors
.
Povolení CORS s atributy
Povolení CORS pomocí atributu [EnableCors] a použití pojmenované zásady pouze na koncové body, které vyžadují CORS, poskytuje nejlepší kontrolu.
Atribut [EnableCors] poskytuje alternativu k použití CORS globálně. Tento [EnableCors]
atribut umožňuje CORS pro vybrané koncové body, nikoli pro všechny koncové body:
[EnableCors]
určuje výchozí zásadu.[EnableCors("{Policy String}")]
určuje pojmenovanou zásadu.
Atribut [EnableCors]
lze použít na:
- Razor Stránka
PageModel
- Ovladač
- Metoda akce kontroleru
U kontrolerů, modelů stránek nebo metod akcí s atributem [EnableCors]
je možné použít různé zásady. [EnableCors]
Když se atribut použije u kontroleru, modelu stránky nebo metody akce a CORS je v middlewaru povolený, použijí se obě zásady. Doporučujeme kombinovat zásady. Pomocí tlačítka[EnableCors]
atribut nebo middleware, ne oba ve stejné aplikaci.
Následující kód použije pro každou metodu jinou zásadu:
[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(),
};
}
}
Následující kód vytvoří dvě zásady CORS:
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();
});
}
}
Nejlepší kontrolu nad omezováním požadavků CORS:
- Používá se
[EnableCors("MyPolicy")]
s pojmenovanými zásadami. - Nedefinujte výchozí zásadu.
- Nepoužívejte směrování koncového bodu.
Kód v další části odpovídá předchozímu seznamu.
Pokyny k testování kódu podobného předchozímu kódu najdete v části Test CORS .
Zakázání CORS
Atribut [DisableCors] nezakazuje CORS, které bylo povoleno směrováním koncového bodu.
Následující kód definuje zásadu "MyPolicy"
CORS:
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();
});
}
}
Následující kód zakáže CORS pro GetValues2
akci:
[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();
}
Předchozí kód:
- Nepovoluje CORS se směrováním koncových bodů.
- Nedefinuje výchozí zásady CORS.
- Pomocí funkce [EnableCors("MyPolicy")] povolí
"MyPolicy"
zásady CORS pro kontroler. - Zakáže CORS pro metodu
GetValues2
.
Pokyny k testování předchozího kódu najdete v části Test CORS .
Možnosti zásad CORS
Tato část popisuje různé možnosti, které je možné nastavit v zásadách CORS:
- Nastavení povolených zdrojů
- Nastavení povolených metod HTTP
- Nastavení hlaviček povolených požadavků
- Nastavení vystavených hlaviček odpovědí
- Přihlašovací údaje v požadavcích mezi zdroji
- Nastavení doby předběžného vypršení platnosti
AddPolicy je volána v Startup.ConfigureServices
. U některých možností může být užitečné nejprve přečíst část Jak CORS funguje .
Nastavení povolených zdrojů
AllowAnyOrigin: Umožňuje CORS požadavky ze všech původů s jakýmkoli schématem (http
nebo https
). AllowAnyOrigin
je nezabezpečený, protože každý web může do aplikace vyhovět žádostem mezi zdroji.
Poznámka:
AllowAnyOrigin
Určení a AllowCredentials
je nezabezpečená konfigurace a může vést k padělání požadavků mezi weby. Služba CORS vrátí neplatnou odpověď CORS, když je aplikace nakonfigurovaná s oběma metodami.
AllowAnyOrigin
ovlivňuje předběžné požadavky a hlavičku Access-Control-Allow-Origin
. Další informace najdete v části Předběžné požadavky .
SetIsOriginAllowedToAllowWildcardSubdomains: Nastaví IsOriginAllowed vlastnost zásady na funkci, která umožňuje, aby zdroje odpovídaly nakonfigurované zástupné doméně při vyhodnocování, zda je původ povolený.
options.AddPolicy("MyAllowSubdomainPolicy",
policy =>
{
policy.WithOrigins("https://*.example.com")
.SetIsOriginAllowedToAllowWildcardSubdomains();
});
Nastavení povolených metod HTTP
- Povoluje libovolnou metodu HTTP:
- Ovlivňuje předběžné požadavky a hlavičku
Access-Control-Allow-Methods
. Další informace najdete v části Předběžné požadavky .
Nastavení hlaviček povolených požadavků
Pokud chcete povolit odesílání konkrétních hlaviček v požadavku CORS, označované jako hlavičky žádosti autora, volání WithHeaders a zadání povolených hlaviček:
options.AddPolicy("MyAllowHeadersPolicy",
policy =>
{
// requires using Microsoft.Net.Http.Headers;
policy.WithOrigins("http://example.com")
.WithHeaders(HeaderNames.ContentType, "x-custom-header");
});
Pokud chcete povolit všechna záhlaví žádosti autora, zavolejte AllowAnyHeader:
options.AddPolicy("MyAllowAllHeadersPolicy",
policy =>
{
policy.WithOrigins("https://*.example.com")
.AllowAnyHeader();
});
AllowAnyHeader
ovlivňuje předběžné požadavky a hlavičku Hlavičky žádostí o přístup. Další informace najdete v části Předběžné požadavky .
Zásady middlewaru CORS odpovídají konkrétním hlavičkám určeným WithHeaders
pouze tehdy, když hlavičky odeslané přesně Access-Control-Request-Headers
odpovídají hlavičkám uvedeným v WithHeaders
.
Představte si například aplikaci nakonfigurovanou takto:
app.UseCors(policy => policy.WithHeaders(HeaderNames.CacheControl));
Middleware CORS odmítne předběžný požadavek s následující hlavičkou požadavku, protože Content-Language
(HeaderNames.ContentLanguage) není uvedený v WithHeaders
:
Access-Control-Request-Headers: Cache-Control, Content-Language
Aplikace vrátí odpověď 200 OK , ale neodesílá hlavičky CORS zpět. Prohlížeč se proto nepokouší o požadavek mezi zdroji.
Nastavení vystavených hlaviček odpovědí
Ve výchozím nastavení prohlížeč nezpřístupňuje do aplikace všechny hlavičky odpovědi. Další informace najdete v tématu Sdílení prostředků mezi zdroji W3C (terminologie): Jednoduchá hlavička odpovědi.
Hlavičky odpovědi, které jsou ve výchozím nastavení k dispozici, jsou:
Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma
Specifikace CORS volá tyto hlavičky jednoduchých hlaviček odpovědi. Pokud chcete aplikaci zpřístupnit další hlavičky, zavolejte WithExposedHeaders:
options.AddPolicy("MyExposeResponseHeadersPolicy",
policy =>
{
policy.WithOrigins("https://*.example.com")
.WithExposedHeaders("x-custom-header");
});
Přihlašovací údaje v požadavcích mezi zdroji
Přihlašovací údaje vyžadují speciální zpracování v požadavku CORS. Ve výchozím nastavení prohlížeč neodesílá přihlašovací údaje s požadavkem mezi zdroji. Přihlašovací údaje zahrnují soubory cookie a schémata ověřování HTTP. Chcete-li odeslat přihlašovací údaje s žádostí mezi zdroji, musí klient nastavit XMLHttpRequest.withCredentials
na true
hodnotu .
Přímé použití XMLHttpRequest
:
var xhr = new XMLHttpRequest();
xhr.open('get', 'https://www.example.com/api/test');
xhr.withCredentials = true;
Pomocí jQuery:
$.ajax({
type: 'get',
url: 'https://www.example.com/api/test',
xhrFields: {
withCredentials: true
}
});
Použití rozhraní Fetch API:
fetch('https://www.example.com/api/test', {
credentials: 'include'
});
Server musí přihlašovací údaje povolit. Pokud chcete povolit přihlašovací údaje mezi zdroji, zavolejte AllowCredentials:
options.AddPolicy("MyMyAllowCredentialsPolicy",
policy =>
{
policy.WithOrigins("http://example.com")
.AllowCredentials();
});
Odpověď HTTP obsahuje hlavičku Access-Control-Allow-Credentials
, která prohlížeči říká, že server povoluje přihlašovací údaje pro požadavek mezi zdroji.
Pokud prohlížeč odešle přihlašovací údaje, ale odpověď neobsahuje platnou Access-Control-Allow-Credentials
hlavičku, prohlížeč nezobrazí odpověď aplikaci a požadavek mezi zdroji selže.
Povolení přihlašovacích údajů mezi zdroji představuje bezpečnostní riziko. Web v jiné doméně může odeslat přihlašovací údaje přihlášeného uživatele do aplikace jménem uživatele bez vědomí uživatele.
Specifikace CORS také uvádí, že nastavení původu na "*"
(všechny zdroje) je neplatné, pokud je hlavička Access-Control-Allow-Credentials
přítomna.
Předběžné požadavky
U některých požadavků CORS prohlížeč před provedením skutečného požadavku odešle další požadavek OPTIONS . Tento požadavek se nazývá předběžný požadavek. Prohlížeč může předběžný požadavek přeskočit, pokud jsou splněny všechny následující podmínky:
- Metoda požadavku je GET, HEAD nebo POST.
- Aplikace nenastavuje jiné hlavičky požadavků než
Accept
,Accept-Language
,Content-Language
, ,Content-Type
neboLast-Event-ID
. - Hlavička
Content-Type
, pokud je nastavená, má jednu z následujících hodnot:application/x-www-form-urlencoded
multipart/form-data
text/plain
Pravidlo hlavičky požadavku nastavené pro požadavek klienta se vztahuje na hlavičky, které aplikace nastaví voláním setRequestHeader
objektu XMLHttpRequest
. Specifikace CORS volá hlavičky požadavku autora. Pravidlo se nevztahuje na hlavičky, které může prohlížeč nastavit, například User-Agent
, Host
nebo Content-Length
.
Následuje příklad odpovědi podobné předběžnému požadavku vytvořenému z tlačítka [Put test] v části Test CORS tohoto dokumentu.
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
Předběžný požadavek používá metodu HTTP OPTIONS . Může obsahovat následující hlavičky:
- Access-Control-Request-Method: Metoda HTTP, která se použije pro skutečný požadavek.
- Hlavičky žádostí řízení přístupu: Seznam hlaviček požadavků, které aplikace nastaví na skutečný požadavek. Jak jsme uvedli dříve, nezahrnuje hlavičky, které prohlížeče nastaví, například
User-Agent
. - Metody Allow-Access-Control-Allow
Pokud je předběžný požadavek odepřen, aplikace vrátí 200 OK
odpověď, ale nenastaví hlavičky CORS. Prohlížeč se proto nepokouší o požadavek mezi zdroji. Příklad odepřené předběžné žádosti najdete v části Testovací CORS tohoto dokumentu.
Pomocí nástrojů F12 konzolová aplikace zobrazí v závislosti na prohlížeči chybu podobnou jedné z následujících možností:
- Firefox: Blokovaný požadavek mezi zdroji: Stejné zásady původu nepovolují čtení vzdáleného prostředku na adrese
https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5
. (Důvod: Požadavek CORS nebyl úspěšný). Další informace - Chromium: Zásady CORS zablokovaly přístup k načtení nahttps://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5 "' z původu'https://cors3.azurewebsites.net: Odpověď na předběžný požadavek neprojde kontrolou řízení přístupu: U požadovaného prostředku není k dispozici žádná hlavička Access-Control-Allow-Origin. Pokud vaše potřeby obsluhují neprůspatnou odpověď, nastavte režim požadavku na no-cors, aby se načítal prostředek se zakázaným CORS.
Pokud chcete povolit konkrétní záhlaví, zavolejte WithHeaders:
options.AddPolicy("MyAllowHeadersPolicy",
policy =>
{
// requires using Microsoft.Net.Http.Headers;
policy.WithOrigins("http://example.com")
.WithHeaders(HeaderNames.ContentType, "x-custom-header");
});
Pokud chcete povolit všechna záhlaví žádosti autora, zavolejte AllowAnyHeader:
options.AddPolicy("MyAllowAllHeadersPolicy",
policy =>
{
policy.WithOrigins("https://*.example.com")
.AllowAnyHeader();
});
Prohlížeče nejsou konzistentní ve způsobu jejich nastavení Access-Control-Request-Headers
. Pokud máte některou z těchto:
- Záhlaví jsou nastavená na cokoli jiného než
"*"
- AllowAnyHeader je volána: Zahrňte alespoň
Accept
,Content-Type
a , aOrigin
navíc všechny vlastní hlavičky, které chcete podporovat.
Automatický předletový kód požadavku
Při použití zásad CORS:
- Globálně voláním
app.UseCors
Startup.Configure
. - Použití atributu
[EnableCors]
ASP.NET Core reaguje na předběžný požadavek OPTIONS.
Povolení CORS na základě jednotlivých koncových bodů v RequireCors
současné době nepodporuje automatické předběžné požadavky.
Toto chování ukazuje část Test CORS tohoto dokumentu.
Atribut [HttpOptions] pro předběžné požadavky
Když je CORS povolená s příslušnými zásadami, ASP.NET Core obvykle automaticky reaguje na předběžné požadavky CORS. V některých scénářích to nemusí být tento případ. Například použití CORS se směrováním koncových bodů.
Následující kód používá atribut [HttpOptions] k vytvoření koncových bodů pro požadavky OPTIONS:
[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);
}
Nastavení doby předběžného vypršení platnosti
Hlavička Access-Control-Max-Age
určuje, jak dlouho může být odpověď na předběžný požadavek uložena do mezipaměti. Chcete-li nastavit toto záhlaví, zavolejte SetPreflightMaxAge:
options.AddPolicy("MySetPreflightExpirationPolicy",
policy =>
{
policy.WithOrigins("http://example.com")
.SetPreflightMaxAge(TimeSpan.FromSeconds(2520));
});
Jak CORS funguje
Tato část popisuje, co se stane v požadavku CORS na úrovni zpráv HTTP.
- CORS není funkce zabezpečení. CORS je standard W3C, který umožňuje serveru uvolnit zásady stejného původu.
- Například herec se zlými úmysly může na vašem webu použít skriptování mezi weby (XSS) a provést žádost mezi weby s podporou CORS k krádeži informací.
- Rozhraní API není bezpečnější tím, že umožňuje CORS.
- Je na klientovi (prohlížeči) a vynucuje CORS. Server spustí požadavek a vrátí odpověď. Je to klient, který vrací chybu a blokuje odpověď. Například některý z následujících nástrojů zobrazí odpověď serveru:
- Fiddler
- .NET HttpClient
- Webový prohlížeč zadáním adresy URL do adresního řádku.
- Je na klientovi (prohlížeči) a vynucuje CORS. Server spustí požadavek a vrátí odpověď. Je to klient, který vrací chybu a blokuje odpověď. Například některý z následujících nástrojů zobrazí odpověď serveru:
- Je to způsob, jak serveru umožnit prohlížečům spouštět požadavek XHR nebo Fetch API mezi zdroji, které by jinak bylo zakázáno.
- Prohlížeče bez CORS nemůžou provádět žádosti mezi zdroji. Před CORS se k obejití tohoto omezení použil JSONP . JSONP nepoužívá XHR, k přijetí odpovědi používá
<script>
značku. Skripty je možné načíst mezi zdroji.
- Prohlížeče bez CORS nemůžou provádět žádosti mezi zdroji. Před CORS se k obejití tohoto omezení použil JSONP . JSONP nepoužívá XHR, k přijetí odpovědi používá
Specifikace CORS zavedla několik nových hlaviček HTTP, které umožňují požadavky mezi zdroji. Pokud prohlížeč podporuje CORS, nastaví tato záhlaví automaticky pro žádosti mezi zdroji. K povolení CORS se nevyžaduje vlastní javascriptový kód.
Následuje příklad požadavku mezi zdroji z tlačítka Test hodnot do https://cors1.azurewebsites.net/api/values
. Hlavička Origin
:
- Poskytuje doménu lokality, která požadavek provádí.
- Vyžaduje se a musí se lišit od hostitele.
Obecné hlavičky
Request URL: https://cors1.azurewebsites.net/api/values
Request Method: GET
Status Code: 200 OK
Hlavičky odpovědi
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
Hlavičky požadavku
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 ...
V OPTIONS
požadavcích server nastaví hlavičku hlavičky Access-Control-Allow-Origin: {allowed origin}
odpovědi v odpovědi. Například nasazená ukázka obsahuje požadavek na tlačítko OPTIONS
Delete [EnableCors] následující hlavičky:
Obecné hlavičky
Request URL: https://cors3.azurewebsites.net/api/TodoItems2/MyDelete2/5
Request Method: OPTIONS
Status Code: 204 No Content
Hlavičky odpovědi
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
Hlavičky požadavku
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
V předchozích hlavičkách odpovědi server nastaví v odpovědi hlavičku Access-Control-Allow-Origin . Hodnota https://cors1.azurewebsites.net
této hlavičky odpovídá Origin
hlavičce požadavku.
Pokud AllowAnyOrigin je volána, Access-Control-Allow-Origin: *
vrátí se hodnota zástupné dokumentace. AllowAnyOrigin
umožňuje jakýkoli původ.
Pokud odpověď hlavičku Access-Control-Allow-Origin
neobsahuje, požadavek mezi zdroji selže. Konkrétně prohlížeč požadavek zakáže. I když server vrátí úspěšnou odpověď, prohlížeč nepřístupní odpověď klientské aplikaci.
Zobrazení požadavků OPTIONS
Ve výchozím nastavení prohlížeče Chrome a Edge nezobrazují požadavky OPTIONS na kartě sítě nástrojů F12. Zobrazení požadavků OPTIONS v těchto prohlížečích:
chrome://flags/#out-of-blink-cors
neboedge://flags/#out-of-blink-cors
- zakažte příznak.
- restartovat.
Firefox zobrazuje ve výchozím nastavení žádosti OPTIONS.
CORS ve službě IIS
Při nasazování do služby IIS musí CORS běžet před ověřováním systému Windows, pokud server není nakonfigurovaný tak, aby povoloval anonymní přístup. Pro podporu tohoto scénáře je potřeba nainstalovat a nakonfigurovat modul CORS služby IIS pro aplikaci.
Testování CORS
Ukázkový soubor ke stažení obsahuje kód pro testování CORS. Podívejte se, jak si stáhnout. Ukázka je projekt rozhraní API s přidanými stránkami Razor :
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();
});
}
}
Upozorňující
WithOrigins("https://localhost:<port>");
by se měla použít pouze k testování ukázkové aplikace podobné ukázkového kódu ke stažení.
ValuesController
Následující body poskytují koncové body pro testování:
[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 poskytuje balíček NuGet Rick.Docs.Samples.RouteInfo a zobrazí informace o trase.
Otestujte předchozí vzorový kód pomocí jednoho z následujících přístupů:
- Spusťte ukázku s
dotnet run
použitím výchozí adresy URLhttps://localhost:5001
souboru . - Spusťte ukázku ze sady Visual Studio s portem nastaveným na 44398 pro adresu URL souboru
https://localhost:44398
.
Použití prohlížeče s nástroji F12:
Vyberte tlačítko Hodnoty a zkontrolujte záhlaví na kartě Síť.
Vyberte tlačítko TEST PUT. Pokyny k zobrazení požadavku OPTIONS najdete v části Zobrazení MOŽNOSTÍ . Test PUT vytvoří dva požadavky, předběžný požadavek OPTIONS a požadavek PUT.
GetValues2 [DisableCors]
Výběrem tlačítka aktivujte neúspěšný požadavek CORS. Jak je uvedeno v dokumentu, odpověď vrátí úspěch 200, ale požadavek CORS není proveden. Výběrem karty Konzola zobrazíte chybu CORS. V závislosti na prohlížeči se zobrazí chyba podobná této:Zásady CORS blokovaly přístup k načtení
'https://cors1.azurewebsites.net/api/values/GetValues2'
z zdroje'https://cors3.azurewebsites.net'
: U požadovaného prostředku není k dispozici žádná hlavička Access-Control-Allow-Origin. Pokud vaše potřeby obsluhují neprůspatnou odpověď, nastavte režim požadavku na no-cors, aby se načítal prostředek se zakázaným CORS.
Koncové body s podporou CORS je možné testovat pomocí nástroje, jako je curl nebo Fiddler. Při použití nástroje se původ požadavku určeného Origin
hlavičkou musí lišit od hostitele, který požadavek přijímá. Pokud požadavek není mezi zdroji založený na hodnotě hlavičky Origin
:
- Není nutné, aby middleware CORS zpracovával požadavek.
- Hlavičky CORS se v odpovědi nevracejí.
Následující příkaz používá curl
k vydání požadavku OPTIONS s informacemi:
curl -X OPTIONS https://cors3.azurewebsites.net/api/TodoItems2/5 -i
Testování CORS se směrováním koncových bodů a [HttpOptions]
Povolení CORS na základě jednotlivých koncových bodů v RequireCors
současné době nepodporuje automatické předběžné požadavky. Zvažte následující kód, který používá směrování koncových bodů k povolení CORS:
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
Následující body poskytují koncové body pro testování:
[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);
}
Otestujte předchozí kód z testovací stránky (https://cors1.azurewebsites.net/test?number=1
) nasazené ukázky.
Tlačítka Delete [EnableCors] a GET [EnableCors] jsou úspěšná, protože koncové body mají [EnableCors]
a reagují na předběžné požadavky. Ostatní koncové body selžou. Tlačítko GET selže, protože JavaScript odesílá:
headers: {
"Content-Type": "x-custom-header"
},
TodoItems2Controller
Následující body poskytují podobné koncové body, ale obsahují explicitní kód pro reakci na požadavky OPTIONS:
[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);
}
Předchozí kód je možné otestovat nasazením ukázky do Azure.In rozevíracího seznamu Kontroleru , výběrem možnosti Preflight a následným nastavením kontroleru. Všechna volání CORS do TodoItems2Controller
koncových bodů jsou úspěšná.