ASP.NET Core'da Çıkış Noktaları Arası İstekleri (CORS) Etkinleştirme

Note

Bu, bu makalenin en son sürümü değildir. Geçerli sürüm için bu makalenin .NET 10 sürümüne bakın.

Warning

ASP.NET Core'un bu sürümü artık desteklenmiyor. Daha fazla bilgi için bkz . .NET ve .NET Core Destek İlkesi. Geçerli sürüm için bu makalenin .NET 10 sürümüne bakın.

Yayımlayanlar Rick Anderson ve Kirk Larkin

Bu makalede, ASP.NET Core uygulamasında Cross-O rigin Resource Sharing'in (CORS) nasıl etkinleştirildiği gösterilmektedir.

Tarayıcı güvenliği, bir web sayfasının web sayfasına hizmet verenden farklı bir etki alanına istekte bulunmasını engeller. Bu kısıtlama aynı çıkış noktası ilkesi olarak adlandırılır. Aynı çıkış noktası ilkesi, kötü amaçlı bir sitenin başka bir siteden hassas verileri okumasını önler. Bazen başka sitelerin uygulamanıza çıkış noktaları arası isteklerde bulunmasına izin vermek isteyebilirsiniz. Daha fazla bilgi için Mozilla CORS makalesine bakın.

Çıkış Noktaları Arası Kaynak Paylaşımı (CORS):

  • Bir sunucunun aynı kaynak ilkesini gevşetmesini sağlayan bir W3C standardıdır.
  • Bir güvenlik özelliği değildir , CORS güvenliği rahatlatır. CORS'ye izin vererek API daha güvenli değildir. Daha fazla bilgi için bkz . CORS nasıl çalışır?
  • Bir sunucunun bazı çıkış noktaları arası isteklere izin verirken diğerlerini reddetmesine izin verir.
  • JSONP gibi önceki tekniklerden daha güvenli ve daha esnektir.

Örnek kodu görüntüleme veya indirme (indirme)

Aynı kaynak

Aynı şemalara, konaklara ve bağlantı noktalarına sahip olan iki URL'nin kaynağı aynıdır (RFC 6454).

Bu iki URL'nin kaynağı aynıdır:

  • https://example.com/foo.html
  • https://example.com/bar.html

Bu URL'lerin çıkış noktaları önceki iki URL'den farklı:

  • https://example.net: Farklı alan adı
  • https://contoso.example.com/foo.html: Farklı alt alan adı
  • http://example.com/foo.html: Farklı düzen
  • https://example.com:9000/foo.html: Farklı bağlantı noktası

CORS'yi etkinleştirme

CORS'yi etkinleştirmenin üç yolu vardır:

[EnableCors] özniteliğini adlandırılmış bir ilkeyle kullanmak, CORS'yi destekleyen uç noktaları sınırlama konusunda en iyi denetimi sağlar.

Warning

UseCors doğru sırada çağrılmalıdır. Daha fazla bilgi için bkz. Ara katman sırası. Örneğin, UseCors kullanılırken UseResponseCachingönce UseResponseCaching çağrılmalıdır.

Her yaklaşım aşağıdaki bölümlerde ayrıntılı olarak anlatılır.

Adlandırılmış ilke ve ara yazılım ile CORS

CORS ara yazılımı çıkış noktaları arası istekleri işler. Aşağıdaki kod, belirtilen kaynaklarla uygulamanın tüm uç noktalarına bir CORS ilkesi uygular:

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();

Yukarıdaki kod:

Uç nokta yönlendirmesinde, CORS ara yazılımı, ile UseRouting çağrıları arasında çalışacak şekilde yapılandırılUseEndpoints.

Yöntem çağrısı, AddCors CORS hizmetlerini uygulamanın hizmet kapsayıcısına ekler:

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();

Daha fazla bilgi için bu belgedeki CORS ilkesi seçeneklerine bakın.

Yöntemler CorsPolicyBuilder , aşağıdaki kodda gösterildiği gibi zincirlenebilir:

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();

Not: Belirtilen URL sonunda eğik çizgi () içermemelidir./ URL / ile bitiyorsa, karşılaştırma false döndürür ve hiçbir başlık döndürülmez.

UseCors ve UseStaticFiles sırası

Genellikle, UseStaticFiles, UseCors'den önce çağrılır. Siteler arası statik dosyaları almak için JavaScript kullanan uygulamaların, UseCors işleminden önce UseStaticFiles çağrısını yapması gerekir.

Varsayılan ilke ve ara yazılım ile CORS

Aşağıdaki vurgulanmış kod, varsayılan CORS ilkesini etkinleştirir:

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();

Yukarıdaki kod, varsayılan CORS ilkesini tüm denetleyici uç noktalarına uygular.

Uç nokta yönlendirmesi ile Cors'i etkinleştirme

Uç nokta yönlendirme ile CORS, uzantı yöntemleri kümesi kullanılarak RequireCors uç nokta temelinde etkinleştirilebilir:

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();

Önceki kodda:

  • app.UseCors CORS ara yazılımını etkinleştirir. Varsayılan ilke yapılandırılmadığından tek app.UseCors() başına CORS'yi etkinleştirmez.
  • /echo ve denetleyici uç noktaları, belirtilen ilkeyi kullanarak çıkış noktaları arası isteklere izin verir.
  • Varsayılan bir ilke belirtilmediğinden, /echo2 ve Razor Pages uç noktaları kaynaklar arası isteklere izin vermez.

[DisableCors] özniteliği ile uç nokta yönlendirmesi tarafından etkinleştirilen CORS'yi devre dışı bırakmazRequireCors.

Yukarıdakine benzer bir kodu test etme yönergeleri için bkz . CORS'yi [EnableCors] özniteliği ve RequireCors yöntemiyle test etme.

CorS'yi özniteliklerle etkinleştirme

CORS'yi [EnableCors] özniteliğiyle etkinleştirmek ve yalnızca CORS gerektiren uç noktalara adlandırılmış bir ilke uygulamak en iyi denetimi sağlar.

[EnableCors] özniteliği, CORS'yi genel olarak uygulamaya bir alternatif sağlar. [EnableCors] özniteliği, tüm uç noktalar yerine seçili uç noktalar için CORS'yi etkinleştirir:

  • [EnableCors] varsayılan ilkeyi belirtir.
  • [EnableCors("{Policy String}")] adlandırılmış bir ilke belirtir.

[EnableCors] Özniteliği şu özelliklere uygulanabilir:

  • Razor Sayfa PageModel
  • Controller
  • Denetleyici eylem yöntemi

[EnableCors] özniteliğiyle denetleyicilere, sayfa modellerine veya eylem yöntemlerine farklı ilkeler uygulanabilir. [EnableCors] Öznitelik bir denetleyiciye, sayfa modeline veya eylem yöntemine uygulandığında ve ara yazılımda CORS etkinleştirildiğinde, her iki ilke de uygulanır. İlkeleri birleştirmenizi önermiyoruz. Şunu kullanın [EnableCors] öznitelik veya ara yazılım, aynı uygulamada ikisi birden değil.

Aşağıdaki kod her yönteme farklı bir ilke uygular:

[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(),
        };
    }
}

Aşağıdaki kod iki CORS ilkesi oluşturur:

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();

CORS isteklerini sınırlamanın en iyi denetimi için:

  • [EnableCors("MyPolicy")] öğesini adlandırılmış bir ilkeyle kullanın.
  • Varsayılan bir ilke tanımlamayın.
  • Uç nokta yönlendirme kullanmayın.

Sonraki bölümdeki kod önceki listeyi karşılar.

CORS'yi devre dışı bırakma

[DisableCors] özniteliği, uç nokta yönlendirmesi tarafından etkinleştirilen CORS'yi devre dışı bırakmaz.

Aşağıdaki kod CORS ilkesini "MyPolicy"tanımlar:

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();

Aşağıdaki kod, GetValues2 eylemi için CORS’u devre dışı bırakır:

[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();

}

Yukarıdaki kod:

  • Uç nokta yönlendirme ile CORS'yi etkinleştirmez.
  • Varsayılan bir CORS ilkesi tanımlamaz.
  • Denetleyici için CORS ilkesini etkinleştirmek üzere "MyPolicy" kullanır.
  • GetValues2 yöntemi için CORS’u devre dışı bırakır.

Önceki kodu test etmeye ilişkin yönergeler için CORS'u Test Etme bölümüne bakın.

CORS ilke seçenekleri

Bu bölümde, CORS ilkesinde ayarlanabilecek çeşitli seçenekler açıklanmaktadır:

AddPolicy içinde Program.cs çağrılır. Bazı seçenekler için öncelikle CORS'nin çalışma şekli bölümünü okumak yararlı olabilir.

İzin verilen çıkış noktalarını ayarlama

AllowAnyOrigin: Herhangi bir şema (http veya https) ile tüm kaynaklardan GELEN CORS isteklerine izin verir. AllowAnyOrigin güvenli değildir çünkü herhangi bir web sitesi uygulamaya çıkış noktaları arası isteklerde bulunabilir.

Warning

AllowAnyOrigin ve AllowCredentials değerlerinin belirtilmesi güvenli olmayan bir yapılandırmadır ve siteler arası istek sahteciliğine neden olabilir. Bir uygulama her iki yöntemle de yapılandırıldığında CORS hizmeti geçersiz bir CORS yanıtı döndürür. Ile birlikte AllowCredentials kullanarak SetIsOriginAllowed(_ => true) yerleşik denetimleri atlamak da güvenli olmayan bir yapılandırmadır.

AllowAnyOrigin, ön kontrol isteklerini ve Access-Control-Allow-Origin üst bilgisini etkiler. Daha fazla bilgi için Ön kontrol istekleri adlı bölüme bakın.

SetIsOriginAllowedToAllowWildcardSubdomains: İlkenin IsOriginAllowed özelliğini, kaynağın izin verilip verilmediğini değerlendirirken çıkış noktalarının yapılandırılmış joker karakter etki alanıyla eşleşmesini sağlayan bir işlev olacak şekilde ayarlar.

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();

Önceki kodda SetIsOriginAllowedToAllowWildcardSubdomains, joker kökeni "https://*.example.com" ile çağrılır. Bu yapılandırma, example.com gibi https://subdomain.example.com veya https://api.example.com alt etki alanlarından gelen CORS isteklerine izin verir. * Joker karakterin alt etki alanı eşleştirmeyi etkinleştirmek için kaynağa eklenmesi gerekir.

İzin verilen HTTP yöntemlerini ayarlama

AllowAnyMethod:

  • Herhangi bir HTTP yöntemine izin verir:
  • Ön kontrol isteklerini ve Access-Control-Allow-Methods üst bilgisini etkiler. Daha fazla bilgi için Ön kontrol istekleri adlı bölüme bakın.

İzin verilen istek üst bilgilerini ayarlayın

Bir CORS isteğinde yazar tanımlı istek üst bilgilerinin gönderilmesine izin vermek için WithHeaders çağrısını yapın ve izin verilen üst bilgileri belirtin:

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();

Tüm author request header'larına izin vermek için AllowAnyHeader çağrısını yapın:

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 preflight isteklerini ve Access-Control-Request-Headers üst bilgisini etkiler. Daha fazla bilgi için Ön kontrol istekleri adlı bölüme bakın.

WithHeaders tarafından belirtilen belirli üstbilgilerle eşleşen bir CORS ara yazılım ilkesi, yalnızca Access-Control-Request-Headers içinde gönderilen üstbilgiler WithHeaders içinde belirtilen üstbilgilerle tam olarak eşleştiğinde mümkündür.

Örneğin, aşağıdaki gibi yapılandırılmış bir uygulamayı göz önünde bulundurun:

app.UseCors(policy => policy.WithHeaders(HeaderNames.CacheControl));

CORS ara yazılımı, Content-Language (HeaderNames.ContentLanguage) WithHeaders içinde listelenmediği için aşağıdaki istek üst bilgisine sahip bir ön kontrol isteğini reddeder:

Access-Control-Request-Headers: Cache-Control, Content-Language

Uygulama bir 204 No Content yanıt döndürür ancak CORS üst bilgilerini geri göndermez. Bu nedenle tarayıcı çıkış noktaları arası isteği denemez.

Erişime açılan yanıt başlıklarını ayarlayın

Varsayılan olarak, tarayıcı tüm yanıt üst bilgilerini uygulamaya sunmaz. Daha fazla bilgi için bkz . W3C Çıkış Noktaları Arası Kaynak Paylaşımı (Terminoloji): Basit Yanıt Üst Bilgisi.

Varsayılan olarak kullanılabilen yanıt üst bilgileri şunlardır:

  • Cache-Control
  • Content-Language
  • Content-Type
  • Expires
  • Last-Modified
  • Pragma

CORS belirtimi bu üst bilgileri basit yanıt üst bilgilerini çağırır. Diğer üst bilgileri uygulamanın kullanımına sunmak için WithExposedHeaders çağrısı yapın:

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();

Kaynaklar arası isteklerde kimlik bilgileri

Kimlik bilgileri, bir CORS isteğinde özel olarak ele alınmalıdır. Varsayılan olarak, tarayıcı çıkış noktaları arası bir istekle kimlik bilgileri göndermez. Kimlik bilgileri, tanımlama bilgilerini ve HTTP kimlik doğrulama şemalarını içerir. Farklı kaynaklar arası bir istekle kimlik bilgilerini göndermek için istemci, XMLHttpRequest.withCredentials değerini true olarak ayarlamalıdır.

XMLHttpRequest doğrudan kullanımı:

var xhr = new XMLHttpRequest();
xhr.open('get', 'https://www.example.com/api/test');
xhr.withCredentials = true;

jQuery kullanma:

$.ajax({
  type: 'get',
  url: 'https://www.example.com/api/test',
  xhrFields: {
    withCredentials: true
  }
});

Fetch API'sini kullanma:

fetch('https://www.example.com/api/test', {
    credentials: 'include'
});

Sunucunun kimlik bilgilerine izin vermesi gerekir. Kaynaklar arası kimlik bilgilerine izin vermek için AllowCredentials çağırın:

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();

HTTP yanıtı, sunucunun kaynaklar arası bir istekte kimlik bilgilerine izin verdiğini tarayıcıya bildiren bir Access-Control-Allow-Credentials üst bilgisi içerir.

Tarayıcı kimlik bilgilerini gönderir ancak yanıt geçerli bir Access-Control-Allow-Credentials başlığı içermiyorsa, tarayıcı yanıtı uygulamanın erişimine açmaz ve kaynaklar arası istek başarısız olur.

Kaynaklar arası kimlik bilgilerine izin vermek güvenlik riskidir. Başka bir etki alanındaki bir web sitesi, kullanıcının bilgisi olmadan oturum açmış bir kullanıcının kimlik bilgilerini kullanıcı adına uygulamaya gönderebilir.

CORS belirtimi ayrıca, "*" üstbilgisi mevcutsa kaynakların Access-Control-Allow-Credentials (tüm kaynaklar) olarak ayarlanmasının geçersiz olduğunu belirtir.

Ön kontrol istekleri

Bazı CORS istekleri için tarayıcı, gerçek isteği yapmadan önce ek bir OPTIONS isteği gönderir. Bu istek, ön kontrol isteği olarak adlandırılır. Tarayıcı, aşağıdaki koşulların tümü doğruysa ön kontrol isteğini atlayabilir:

  • İstek yöntemi GET, HEAD veya POST şeklindedir.
  • Uygulama, Accept, Accept-Language, Content-Language, Content-Type veya Last-Event-ID dışında istek üst bilgileri ayarlamaz.
  • Content-Type Üst bilgi ayarlanırsa aşağıdaki değerlerden birine sahiptir:
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain

İstemci isteği için ayarlanan istek üst bilgilerine ilişkin kural, uygulamanın setRequestHeader nesnesi üzerinde XMLHttpRequest çağrısı yaparak ayarladığı üst bilgiler için geçerlidir. CORS spesifikasyonu bu üst bilgileri yazar istek üst bilgileri olarak adlandırır. Kural, tarayıcının ayarlayabileceğiniz , User-Agentveya Hostgibi Content-Lengthüst bilgiler için geçerli değildir.

Note

Bu makale, örnek kodun iki Azure web sitesine dağıtılmasıyla oluşturulan URL'leri içerir: https://cors3.azurewebsites.net ve https://cors.azurewebsites.net.

Aşağıda, bu belgenin Test CORS bölümündeki [Test et] düğmesinden yapılan denetim öncesi isteğine benzer bir örnek yanıt verilmiştir.

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

Ön kontrol isteği, HTTP OPTIONS yöntemini kullanır. Aşağıdaki üst bilgileri içerebilir:

  • Access-Control-Request-Method: Gerçek istek için kullanılacak HTTP yöntemi.
  • Access-Control-Request-Headers: Uygulamanın gerçek istekte ayar yaptığı istek üst bilgilerinin listesi. Daha önce belirtildiği gibi, bu, tarayıcının ayardığı üst bilgileri (gibi User-Agent) içermez.

Ön kontrol isteği reddedilirse uygulama 204 No Content yanıtı döndürür, ancak CORS başlıklarını ayarlamaz. Bu nedenle tarayıcı çıkış noktaları arası isteği denemez. Reddedilmiş bir preflight isteği örneğini görmek için bu belgedeki CORS’yi Test Et bölümüne bakın.

F12 araçlarını kullanarak, konsol uygulaması tarayıcıya bağlı olarak aşağıdakilerden birine benzer bir hata gösterir:

  • Firefox: Çapraz Kaynak İsteği Engellendi: Aynı Kaynak İlkesi, https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5 konumundaki uzak kaynağın okunmasına izin vermiyor. (Neden: CORS isteği başarılı olmadı). Daha fazla bilgi edinin
  • Chromium tabanlı: 'https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5' kaynağından 'https://cors3.azurewebsites.net' konumuna getirme erişimi CORS ilkesi tarafından engellendi: Ön kontrol isteğine verilen yanıt, erişim denetimi kontrolünden geçmiyor: İstenen kaynakta 'Access-Control-Allow-Origin' üst bilgisi bulunmuyor. Opak yanıt gereksinimlerinize uygunsa, CORS devre dışı bırakılmış olan kaynağı getirmek için isteğin modunu 'cors yok' olarak ayarlayın.

Belirli üstbilgilere izin vermek için WithHeaders çağrısını yapın:

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();

Tüm author request header'larına izin vermek için AllowAnyHeader çağrısını yapın:

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();

Tarayıcılar, Access-Control-Request-Headers öğesini nasıl ayarladıkları konusunda tutarlı değildir. Aşağıdakilerden biri varsa:

  • Üstbilgiler, "*" dışında herhangi bir değere ayarlanır
  • AllowAnyHeader çağrılır: En az Accept, Content-Typeve Originile birlikte, desteklemek istediğiniz özel üst bilgileri ekleyin.

Otomatik ön kontrol isteği kodu

CORS ilkesi aşağıdakilerden biri uygulandığında:

  • app.UseCors içinde Program.cs çağrısı yaparak genel olarak.
  • özniteliğini [EnableCors] kullanma.

ASP.NET Core, denetim öncesi SEÇENEKLER isteğine yanıt verir.

Bu belgenin Test CORS bölümünde bu davranış gösterilmektedir.

Preflight istekleri için [HttpOptions] özniteliği

CORS uygun ilkeyle etkinleştirildiğinde, ASP.NET Core genellikle CORS denetim öncesi isteklerine otomatik olarak yanıt verir.

Aşağıdaki kod, OPTIONS istekleri için uç noktalar oluşturmak için [HttpOptions] özniteliğini kullanır:

[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);
    }

Yukarıdaki kodu test etme yönergeleri için bkz . CORS'yi [EnableCors] özniteliği ve RequireCors yöntemiyle test etme.

Denetim öncesi süre sonu süresini ayarlama

Access-Control-Max-Age üst bilgisi, preflight isteğine verilen yanıtın ne kadar süreyle önbellekte tutulabileceğini belirtir. Bu üst bilgiyi ayarlamak için SetPreflightMaxAge çağrısını yapın:

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();

Bir uç noktada CORS'yi etkinleştirme

CORS nasıl çalışır?

Bu bölüm, HTTP iletileri düzeyinde bir CORS isteğinde neler olduğunu açıklar.

  • CORS bir güvenlik özelliği değildir . CORS, bir sunucunun aynı kaynak ilkesini gevşetmesini sağlayan bir W3C standardıdır.
  • CORS'ye izin vererek API daha güvenli değildir.
    • CORS'yi zorunlu kılmak istemciye (tarayıcıya) bağlı. Sunucu isteği yürütür ve yanıtı döndürür; hata döndüren ve yanıtı engelleyen istemcidir. Örneğin, aşağıdaki araçlardan herhangi biri sunucu yanıtını görüntüler:
  • Bu, bir sunucunun tarayıcıların normalde yasak olacak farklı bir origin’e yönelik XHR veya Fetch API isteği yürütmesine izin vermesinin bir yoludur.
    • CORS'siz tarayıcılar çıkış noktaları arası istekler yapamaz. CORS'ye başlamadan önce, bu kısıtlamayı aşmak için JSONP kullanıldı. JSONP XHR kullanmaz, yanıtı almak için etiketini kullanır <script> . Betiklerin farklı kaynaklardan yüklenmesine izin verilir.

CORS belirtimi, çıkış noktaları arası istekleri etkinleştiren birkaç yeni HTTP üst bilgisi kullanıma sunulmuştur. Tarayıcı CORS'yi destekliyorsa çıkış noktaları arası istekler için bu üst bilgileri otomatik olarak ayarlar. CORS'yi etkinleştirmek için özel JavaScript kodu gerekmez.

Aşağıda, Değerler test düğmesinden https://cors1.azurewebsites.net/api/values konumuna yapılan farklı kaynaktan gelen bir isteğin örneği verilmiştir. Origin başlığı:

  • İstekte bulunan sitenin etki alanını sağlar.
  • Zorunludur ve ana bilgisayardan farklı olmalıdır.

Genel üst bilgiler

Request URL: https://cors1.azurewebsites.net/api/values
Request Method: GET
Status Code: 200 OK

Yanıt üst bilgileri

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

İstek üst bilgileri

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 ...

OPTIONS isteklerinde sunucu, yanıtta Yanıt üst bilgileriAccess-Control-Allow-Origin: {allowed origin} üst bilgisini ayarlar. Örneğin, örnek kodda Delete [EnableCors] düğme OPTIONS isteği aşağıdaki üst bilgileri içerir:

Genel üst bilgiler

Request URL: https://cors3.azurewebsites.net/api/TodoItems2/MyDelete2/5
Request Method: OPTIONS
Status Code: 204 No Content

Yanıt üst bilgileri

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

İstek üst bilgileri

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

Yukarıdaki Yanıt üst bilgilerinde, sunucu yanıttaki Access-Control-Allow-Origin üst bilgisini ayarlar. https://cors1.azurewebsites.net Bu üst bilginin değeri istekten alınan Origin üst bilgiyle eşleşir.

AllowAnyOrigin çağrılırsa, joker karakter değeri olan Access-Control-Allow-Origin: * döndürülür. AllowAnyOrigin herhangi bir çıkış noktası sağlar.

Yanıt Access-Control-Allow-Origin başlığını içermiyorsa, kaynaklar arası istek başarısız olur. Özellikle, tarayıcı isteğe izin vermemektedir. Sunucu başarılı bir yanıt döndürse bile, tarayıcı yanıtı istemci uygulaması için kullanılabilir hale getirmez.

HTTP'den HTTPS'ye yönlendirme, CORS ön kontrol isteğinde ERR_INVALID_REDIRECT hatasına neden olur

UseHttpsRedirection tarafından HTTPS'ye yönlendirilen, HTTP kullanan bir uç noktaya yapılan istekler ERR_INVALID_REDIRECT on the CORS preflight request ile başarısız olur.

API projeleri, istekleri HTTPS'ye yeniden yönlendirmek için kullanmak UseHttpsRedirection yerine HTTP isteklerini reddedebilir.

IIS'de CORS

IIS'ye dağıtım yaparken, sunucu anonim erişime izin verecek şekilde yapılandırılmamışsa CORS'nin Windows Kimlik Doğrulamasından önce çalışması gerekir. Bu senaryoyu desteklemek için IIS CORS modülünün uygulama için yüklenmesi ve yapılandırılması gerekir.

CORS'i test edin

Örnek indirmede CORS'yi test etmek için kod bulunur. İndirmeyi öğrenin. Örnek, Razor Pages eklenmiş bir API projesidir:

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();

Warning

WithOrigins("https://localhost:<port>");yalnızca indirme örnek koduna benzer bir örnek uygulamayı test etmek için kullanılmalıdır.

Note

Visual Studio'da launchSettings.json kullanıyorsanız veya VS Code'da C# hata ayıklama ayarlarını yapılandırıyorsanız ve yerel olarak hata ayıklamak için IIS Express kullanıyorsanız, için IIS Express'i yapılandırdığınızdan emin olun. "anonymousAuthentication" false olduğunda, ASP.NET Core web ortamı ana bilgisayarı herhangi bir ön uçuş isteğini görmez. Özellikle NTLM kimlik doğrulaması ()"windowsAuthentication": true kullanıyorsanız, NTLM sınama yanıtının ilk adımı web tarayıcısına bir 401 sınaması göndermektir ve bu da denetim öncesi yolunuzun doğru yapılandırıldığını doğrulamayı zorlaştırabilir.

Aşağıdaki ValuesController, test etmek için uç noktaları sunar:

[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, Rick.Docs.Samples.RouteInfo NuGet paketi tarafından sağlanır ve yol bilgilerini görüntüler.

Aşağıdaki yaklaşımlardan birini kullanarak yukarıdaki örnek kodu test edin:

  • Örneği, dotnet run varsayılan URL’sini kullanarak https://localhost:5001 ile çalıştırın.
  • URL’si https://localhost:44398 olan örneği, bağlantı noktası 44398 olarak ayarlanmış şekilde Visual Studio’dan çalıştırın.

F12 araçlarıyla tarayıcı kullanma:

  • Değerler düğmesini seçin ve Ağ sekmesindeki üst bilgileri gözden geçirin.

  • PUT test düğmesini seçin. OPTIONS isteğinin nasıl görüntüleneceğine ilişkin yönergeler için OPTIONS isteklerini görüntüleme bölümüne bakın. PUT testi iki istek oluşturur: OPTIONS ön uçuş isteği ve PUT isteği.

  • GetValues2 [DisableCors] Başarısız bir CORS isteğini tetikleme düğmesini seçin. Belgede belirtildiği gibi yanıt 200 başarı döndürür, ancak CORS isteği yapılmaz. CORS hatasını görmek için Konsol sekmesini seçin. Tarayıcıya bağlı olarak, aşağıdakine benzer bir hata görüntülenir:

    'https://cors1.azurewebsites.net/api/values/GetValues2' origin’inden 'https://cors3.azurewebsites.net' konumundaki kaynağa erişim CORS ilkesi tarafından engellendi: İstenen kaynakta 'Access-Control-Allow-Origin' üst bilgisi bulunmuyor. Opak yanıt gereksinimlerinize uygunsa, CORS devre dışı bırakılmış olan kaynağı getirmek için isteğin modunu 'cors yok' olarak ayarlayın.

CORS özellikli uç noktalar curl veya Fiddler gibi bir araçla test edilebilir. Bir araç kullanılırken, Origin üst bilgisinde belirtilen isteğin kaynağı, isteği alan ana bilgisayardan farklı olmalıdır. İstek, üst bilgisinin değerine göre Origin değilse:

  • CORS ara yazılımının isteği işlemesine gerek yoktur.
  • CORS başlıkları yanıtta döndürülmüyor.

Aşağıdaki komut, bilgi içeren bir OPTIONS isteği göndermek için kullanır curl :

curl -X OPTIONS https://cors3.azurewebsites.net/api/TodoItems2/5 -i

CORS'yi [EnableCors] özniteliği ve RequireCors yöntemiyle test edin

uç nokta yönlendirmesini kullanarak CORS'yi her bir uç nokta için etkinleştiren RequireCors aşağıdaki kodu göz önünde bulundurun:

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();

Yalnızca /echo uç noktasının, belirtilen ilkeyi kullanarak kaynaklar arası isteklere izin vermek için RequireCors kullandığına dikkat edin. Aşağıdaki denetleyiciler [EnableCors] özniteliğini kullanarak CORS'yi etkinleştirir.

Aşağıdaki TodoItems1Controller test amaçlı uç noktalar sağlar:

[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);
}

Delete [EnableCors] ve GET [EnableCors] düğmeleri başarılı olur, çünkü uç noktalarında [EnableCors] bulunur ve preflight isteklerine yanıt verirler. Diğer uç noktalar başarısız olur. JavaScript şunları gönderdiğinden GET düğmesi başarısız oluyor:

 headers: {
      "Content-Type": "x-custom-header"
 },

Aşağıdakiler TodoItems2Controller benzer uç noktalar sağlar, ancak SEÇENEKLER isteklerine yanıt vermek için açık kod içerir:

[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);
}

Yukarıdaki kod, örneği Azure'a dağıtarak test edilebilir. Controller açılır listesinden Preflight öğesini ve ardından Denetleyiciyi Ayarla seçin. Uç noktalara yapılan TodoItems2Controller tüm CORS çağrıları başarılı olur.

Ek kaynaklar

Yayımlayanlar Rick Anderson ve Kirk Larkin

Bu makalede, ASP.NET Core uygulamasında CORS'nin nasıl etkinleştirileceği gösterilmektedir.

Tarayıcı güvenliği, bir web sayfasının web sayfasına hizmet verenden farklı bir etki alanına istekte bulunmasını engeller. Bu kısıtlama aynı çıkış noktası ilkesi olarak adlandırılır. Aynı çıkış noktası ilkesi, kötü amaçlı bir sitenin başka bir siteden hassas verileri okumasını önler. Bazen başka sitelerin uygulamanıza çıkış noktaları arası isteklerde bulunmasına izin vermek isteyebilirsiniz. Daha fazla bilgi için Mozilla CORS makalesine bakın.

Çıkış Noktaları Arası Kaynak Paylaşımı (CORS):

  • Bir sunucunun aynı kaynak ilkesini gevşetmesini sağlayan bir W3C standardıdır.
  • Bir güvenlik özelliği değildir , CORS güvenliği rahatlatır. CORS'ye izin vererek API daha güvenli değildir. Daha fazla bilgi için bkz . CORS nasıl çalışır?
  • Bir sunucunun bazı çıkış noktaları arası isteklere izin verirken diğerlerini reddetmesine izin verir.
  • JSONP gibi önceki tekniklerden daha güvenli ve daha esnektir.

Örnek kodu görüntüleme veya indirme (indirme)

Aynı kaynak

Aynı şemalara, konaklara ve bağlantı noktalarına sahip olan iki URL'nin kaynağı aynıdır (RFC 6454).

Bu iki URL'nin kaynağı aynıdır:

  • https://example.com/foo.html
  • https://example.com/bar.html

Bu URL'lerin çıkış noktaları önceki iki URL'den farklı:

  • https://example.net: Farklı alan adı
  • https://www.example.com/foo.html: Farklı alt alan adı
  • http://example.com/foo.html: Farklı düzen
  • https://example.com:9000/foo.html: Farklı bağlantı noktası

CORS'yi etkinleştirme

CORS'yi etkinleştirmenin üç yolu vardır:

[EnableCors] özniteliğini adlandırılmış bir ilkeyle kullanmak, CORS'yi destekleyen uç noktaları sınırlama konusunda en iyi denetimi sağlar.

Warning

UseCors doğru sırada çağrılmalıdır. Daha fazla bilgi için bkz. Ara katman sırası. Örneğin, UseCors kullanılırken UseResponseCachingönce UseResponseCaching çağrılmalıdır.

Her yaklaşım aşağıdaki bölümlerde ayrıntılı olarak anlatılır.

Adlandırılmış ilke ve ara yazılım ile CORS

CORS ara yazılımı çıkış noktaları arası istekleri işler. Aşağıdaki kod, belirtilen kaynaklarla uygulamanın tüm uç noktalarına bir CORS ilkesi uygular:

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();

Yukarıdaki kod:

Uç nokta yönlendirmesinde, CORS ara yazılımı, ile UseRouting çağrıları arasında çalışacak şekilde yapılandırılUseEndpoints.

Yöntem çağrısı, AddCors CORS hizmetlerini uygulamanın hizmet kapsayıcısına ekler:

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();

Daha fazla bilgi için bu belgedeki CORS ilkesi seçeneklerine bakın.

Yöntemler CorsPolicyBuilder , aşağıdaki kodda gösterildiği gibi zincirlenebilir:

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();

Not: Belirtilen URL sonunda eğik çizgi () içermemelidir./ URL / ile bitiyorsa, karşılaştırma false döndürür ve hiçbir başlık döndürülmez.

Warning

UseCors, UseRouting öğesinden sonra ve UseAuthorization öğesinden önce yerleştirilmelidir. Bu, CORS üst bilgilerinin hem yetkili hem de yetkisiz çağrılar için yanıta dahil edilmesini sağlamaktır.

UseCors ve UseStaticFiles sırası

Genellikle, UseStaticFiles, UseCors'den önce çağrılır. Siteler arası statik dosyaları almak için JavaScript kullanan uygulamaların, UseCors işleminden önce UseStaticFiles çağrısını yapması gerekir.

Varsayılan ilke ve ara yazılım ile CORS

Aşağıdaki vurgulanmış kod, varsayılan CORS ilkesini etkinleştirir:

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();

Yukarıdaki kod, varsayılan CORS ilkesini tüm denetleyici uç noktalarına uygular.

Uç nokta yönlendirmesi ile Cors'i etkinleştirme

Uç nokta yönlendirme ile CORS, uzantı yöntemleri kümesi kullanılarak RequireCors uç nokta temelinde etkinleştirilebilir:

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();

Önceki kodda:

  • app.UseCors CORS ara yazılımını etkinleştirir. Varsayılan ilke yapılandırılmadığından tek app.UseCors() başına CORS'yi etkinleştirmez.
  • /echo ve denetleyici uç noktaları, belirtilen ilkeyi kullanarak çıkış noktaları arası isteklere izin verir.
  • Varsayılan bir ilke belirtilmediğinden, /echo2 ve Razor Pages uç noktaları kaynaklar arası isteklere izin vermez.

[DisableCors] özniteliği ile uç nokta yönlendirmesi tarafından etkinleştirilen CORS'yi devre dışı bırakmazRequireCors.

.NET 7'de özniteliğin [EnableCors] bir parametre geçirmesi gerekir veya yoldaki belirsiz bir eşleşmeden ASP0023 Uyarısı oluşturulur. .NET 8 veya üzeri, ASP0023 uyarısını oluşturmaz.

[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);
}

Yukarıdakine benzer bir kodu test etme yönergeleri için bkz . CORS'yi [EnableCors] özniteliği ve RequireCors yöntemiyle test etme.

CorS'yi özniteliklerle etkinleştirme

CORS'yi [EnableCors] özniteliğiyle etkinleştirmek ve yalnızca CORS gerektiren uç noktalara adlandırılmış bir ilke uygulamak en iyi denetimi sağlar.

[EnableCors] özniteliği, CORS'yi genel olarak uygulamaya bir alternatif sağlar. [EnableCors] özniteliği, tüm uç noktalar yerine seçili uç noktalar için CORS'yi etkinleştirir:

  • [EnableCors] varsayılan ilkeyi belirtir.
  • [EnableCors("{Policy String}")] adlandırılmış bir ilke belirtir.

[EnableCors] Özniteliği şu özelliklere uygulanabilir:

  • Razor Sayfa PageModel
  • Controller
  • Denetleyici eylem yöntemi

[EnableCors] özniteliğiyle denetleyicilere, sayfa modellerine veya eylem yöntemlerine farklı ilkeler uygulanabilir. [EnableCors] Öznitelik bir denetleyiciye, sayfa modeline veya eylem yöntemine uygulandığında ve ara yazılımda CORS etkinleştirildiğinde, her iki ilke de uygulanır. İlkeleri birleştirmenizi önermiyoruz. Şunu kullanın [EnableCors] öznitelik veya ara yazılım, aynı uygulamada ikisi birden değil.

Aşağıdaki kod her yönteme farklı bir ilke uygular:

[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(),
        };
    }
}

Aşağıdaki kod iki CORS ilkesi oluşturur:

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();

CORS isteklerini sınırlamanın en iyi denetimi için:

  • [EnableCors("MyPolicy")] öğesini adlandırılmış bir ilkeyle kullanın.
  • Varsayılan bir ilke tanımlamayın.
  • Uç nokta yönlendirme kullanmayın.

Sonraki bölümdeki kod önceki listeyi karşılar.

CORS'yi devre dışı bırakma

[DisableCors] özniteliği, uç nokta yönlendirmesi tarafından etkinleştirilen CORS'yi devre dışı bırakmaz.

Aşağıdaki kod CORS ilkesini "MyPolicy"tanımlar:

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();

Aşağıdaki kod, GetValues2 eylemi için CORS’u devre dışı bırakır:

[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();

}

Yukarıdaki kod:

  • Uç nokta yönlendirme ile CORS'yi etkinleştirmez.
  • Varsayılan bir CORS ilkesi tanımlamaz.
  • Denetleyici için CORS ilkesini etkinleştirmek üzere "MyPolicy" kullanır.
  • GetValues2 yöntemi için CORS’u devre dışı bırakır.

Önceki kodu test etmeye ilişkin yönergeler için CORS'u Test Etme bölümüne bakın.

CORS ilke seçenekleri

Bu bölümde, CORS ilkesinde ayarlanabilecek çeşitli seçenekler açıklanmaktadır:

AddPolicy içinde Program.cs çağrılır. Bazı seçenekler için öncelikle CORS'nin çalışma şekli bölümünü okumak yararlı olabilir.

İzin verilen çıkış noktalarını ayarlama

AllowAnyOrigin: Herhangi bir şema (http veya https) ile tüm kaynaklardan GELEN CORS isteklerine izin verir. AllowAnyOrigin güvenli değildir çünkü herhangi bir web sitesi uygulamaya çıkış noktaları arası isteklerde bulunabilir.

Note

AllowAnyOrigin ve AllowCredentials değerlerinin belirtilmesi güvenli olmayan bir yapılandırmadır ve siteler arası istek sahteciliğine neden olabilir. Bir uygulama her iki yöntemle de yapılandırıldığında CORS hizmeti geçersiz bir CORS yanıtı döndürür.

AllowAnyOrigin, ön kontrol isteklerini ve Access-Control-Allow-Origin üst bilgisini etkiler. Daha fazla bilgi için Ön kontrol istekleri adlı bölüme bakın.

SetIsOriginAllowedToAllowWildcardSubdomains: İlkenin IsOriginAllowed özelliğini, kaynağın izin verilip verilmediğini değerlendirirken çıkış noktalarının yapılandırılmış joker karakter etki alanıyla eşleşmesini sağlayan bir işlev olacak şekilde ayarlar.

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();

Önceki kodda SetIsOriginAllowedToAllowWildcardSubdomains, joker kökeni "https://*.example.com" ile çağrılır. Bu yapılandırma, example.com gibi https://subdomain.example.com veya https://api.example.com alt etki alanlarından gelen CORS isteklerine izin verir. * Joker karakterin alt etki alanı eşleştirmeyi etkinleştirmek için kaynağa eklenmesi gerekir.

İzin verilen HTTP yöntemlerini ayarlama

AllowAnyMethod:

  • Herhangi bir HTTP yöntemine izin verir:
  • Ön kontrol isteklerini ve Access-Control-Allow-Methods üst bilgisini etkiler. Daha fazla bilgi için Ön kontrol istekleri adlı bölüme bakın.

İzin verilen istek üst bilgilerini ayarlayın

Bir CORS isteğinde yazar tanımlı istek üst bilgilerinin gönderilmesine izin vermek için WithHeaders çağrısını yapın ve izin verilen üst bilgileri belirtin:

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();

Tüm author istek üst bilgilerine izin vermek için AllowAnyHeader çağırın:

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 preflight isteklerini ve Access-Control-Request-Headers üst bilgisini etkiler. Daha fazla bilgi için Ön kontrol istekleri adlı bölüme bakın.

WithHeaders tarafından belirtilen belirli üstbilgilerle eşleşen bir CORS ara yazılım ilkesi, yalnızca Access-Control-Request-Headers içinde gönderilen üstbilgiler WithHeaders içinde belirtilen üstbilgilerle tam olarak eşleştiğinde mümkündür.

Örneğin, aşağıdaki gibi yapılandırılmış bir uygulamayı göz önünde bulundurun:

app.UseCors(policy => policy.WithHeaders(HeaderNames.CacheControl));

CORS ara yazılımı, Content-Language (HeaderNames.ContentLanguage) WithHeaders içinde listelenmediği için aşağıdaki istek üst bilgisine sahip bir ön kontrol isteğini reddeder:

Access-Control-Request-Headers: Cache-Control, Content-Language

Uygulama 200 Tamam yanıtı döndürür ancak CORS üst bilgilerini geri göndermez. Bu nedenle tarayıcı çıkış noktaları arası isteği denemez.

Erişime açılan yanıt başlıklarını ayarlayın

Varsayılan olarak, tarayıcı tüm yanıt üst bilgilerini uygulamaya sunmaz. Daha fazla bilgi için bkz . W3C Çıkış Noktaları Arası Kaynak Paylaşımı (Terminoloji): Basit Yanıt Üst Bilgisi.

Varsayılan olarak kullanılabilen yanıt üst bilgileri şunlardır:

  • Cache-Control
  • Content-Language
  • Content-Type
  • Expires
  • Last-Modified
  • Pragma

CORS belirtimi bu üst bilgileri basit yanıt üst bilgilerini çağırır. Diğer üst bilgileri uygulamanın kullanımına sunmak için WithExposedHeaders çağrısı yapın:

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();

Kaynaklar arası isteklerde kimlik bilgileri

Kimlik bilgileri, bir CORS isteğinde özel olarak ele alınmalıdır. Varsayılan olarak, tarayıcı çıkış noktaları arası bir istekle kimlik bilgileri göndermez. Kimlik bilgileri, tanımlama bilgilerini ve HTTP kimlik doğrulama şemalarını içerir. Farklı kaynaklar arası bir istekle kimlik bilgilerini göndermek için istemci, XMLHttpRequest.withCredentials değerini true olarak ayarlamalıdır.

XMLHttpRequest doğrudan kullanımı:

var xhr = new XMLHttpRequest();
xhr.open('get', 'https://www.example.com/api/test');
xhr.withCredentials = true;

jQuery kullanma:

$.ajax({
  type: 'get',
  url: 'https://www.example.com/api/test',
  xhrFields: {
    withCredentials: true
  }
});

Fetch API'sini kullanma:

fetch('https://www.example.com/api/test', {
    credentials: 'include'
});

Sunucunun kimlik bilgilerine izin vermesi gerekir. Kaynaklar arası kimlik bilgilerine izin vermek için AllowCredentials çağırın:

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();

HTTP yanıtı, sunucunun kaynaklar arası bir istekte kimlik bilgilerine izin verdiğini tarayıcıya bildiren bir Access-Control-Allow-Credentials üst bilgisi içerir.

Tarayıcı kimlik bilgilerini gönderir ancak yanıt geçerli bir Access-Control-Allow-Credentials başlığı içermiyorsa, tarayıcı yanıtı uygulamanın erişimine açmaz ve kaynaklar arası istek başarısız olur.

Kaynaklar arası kimlik bilgilerine izin vermek güvenlik riskidir. Başka bir etki alanındaki bir web sitesi, kullanıcının bilgisi olmadan oturum açmış bir kullanıcının kimlik bilgilerini kullanıcı adına uygulamaya gönderebilir.

CORS belirtimi ayrıca, "*" üstbilgisi mevcutsa kaynakların Access-Control-Allow-Credentials (tüm kaynaklar) olarak ayarlanmasının geçersiz olduğunu belirtir.

Ön kontrol istekleri

Bazı CORS istekleri için tarayıcı, gerçek isteği yapmadan önce ek bir OPTIONS isteği gönderir. Bu istek, ön kontrol isteği olarak adlandırılır. Tarayıcı, aşağıdaki koşulların tümü doğruysa ön kontrol isteğini atlayabilir:

  • İstek yöntemi GET, HEAD veya POST şeklindedir.
  • Uygulama, Accept, Accept-Language, Content-Language, Content-Type veya Last-Event-ID dışında istek üst bilgileri ayarlamaz.
  • Content-Type Üst bilgi ayarlanırsa aşağıdaki değerlerden birine sahiptir:
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain

İstemci isteği için ayarlanan istek üst bilgilerine ilişkin kural, uygulamanın setRequestHeader nesnesi üzerinde XMLHttpRequest çağrısı yaparak ayarladığı üst bilgiler için geçerlidir. CORS spesifikasyonu bu üst bilgileri yazar istek üst bilgileri olarak adlandırır. Kural, tarayıcının ayarlayabileceğiniz , User-Agentveya Hostgibi Content-Lengthüst bilgiler için geçerli değildir.

Aşağıda, bu belgenin Test CORS bölümündeki [Test et] düğmesinden yapılan denetim öncesi isteğine benzer bir örnek yanıt verilmiştir.

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

Ön kontrol isteği, HTTP OPTIONS yöntemini kullanır. Aşağıdaki üst bilgileri içerebilir:

Ön kontrol isteği reddedilirse uygulama 200 OK yanıtı döndürür, ancak CORS başlıklarını ayarlamaz. Bu nedenle tarayıcı çıkış noktaları arası isteği denemez. Reddedilmiş bir preflight isteği örneğini görmek için bu belgedeki CORS’yi Test Et bölümüne bakın.

F12 araçlarını kullanarak, konsol uygulaması tarayıcıya bağlı olarak aşağıdakilerden birine benzer bir hata gösterir:

  • Firefox: Çapraz Kaynak İsteği Engellendi: Aynı Kaynak İlkesi, https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5 konumundaki uzak kaynağın okunmasına izin vermiyor. (Neden: CORS isteği başarılı olmadı). Daha fazla bilgi edinin
  • Chromium tabanlı: 'https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5' kaynağından 'https://cors3.azurewebsites.net' konumuna getirme erişimi CORS ilkesi tarafından engellendi: Ön kontrol isteğine verilen yanıt, erişim denetimi kontrolünden geçmiyor: İstenen kaynakta 'Access-Control-Allow-Origin' üst bilgisi bulunmuyor. Opak yanıt gereksinimlerinize uygunsa, CORS devre dışı bırakılmış olan kaynağı getirmek için isteğin modunu 'cors yok' olarak ayarlayın.

Belirli üstbilgilere izin vermek için WithHeaders çağrısını yapın:

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();

Tüm author istek üst bilgilerine izin vermek için AllowAnyHeader çağırın:

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();

Tarayıcılar, Access-Control-Request-Headers öğesini nasıl ayarladıkları konusunda tutarlı değildir. Aşağıdakilerden biri varsa:

  • Üstbilgiler, "*" dışında herhangi bir değere ayarlanır
  • AllowAnyHeader çağrılır: En az Accept, Content-Typeve Originile birlikte, desteklemek istediğiniz özel üst bilgileri ekleyin.

Otomatik ön kontrol isteği kodu

CORS ilkesi aşağıdakilerden biri uygulandığında:

  • app.UseCors içinde Program.cs çağrısı yaparak genel olarak.
  • özniteliğini [EnableCors] kullanma.

ASP.NET Core, denetim öncesi SEÇENEKLER isteğine yanıt verir.

Bu belgenin Test CORS bölümünde bu davranış gösterilmektedir.

Preflight istekleri için [HttpOptions] özniteliği

CORS uygun ilkeyle etkinleştirildiğinde, ASP.NET Core genellikle CORS denetim öncesi isteklerine otomatik olarak yanıt verir.

Aşağıdaki kod, OPTIONS istekleri için uç noktalar oluşturmak için [HttpOptions] özniteliğini kullanır:

[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);
    }

Yukarıdaki kodu test etme yönergeleri için bkz . CORS'yi [EnableCors] özniteliği ve RequireCors yöntemiyle test etme.

Denetim öncesi süre sonu süresini ayarlama

Access-Control-Max-Age üst bilgisi, preflight isteğine verilen yanıtın ne kadar süreyle önbellekte tutulabileceğini belirtir. Bu üst bilgiyi ayarlamak için SetPreflightMaxAge çağrısını yapın:

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();

Bir uç noktada CORS'yi etkinleştirme

CORS nasıl çalışır?

Bu bölüm, HTTP iletileri düzeyinde bir CORS isteğinde neler olduğunu açıklar.

  • CORS bir güvenlik özelliği değildir . CORS, bir sunucunun aynı kaynak ilkesini gevşetmesini sağlayan bir W3C standardıdır.
  • CORS'ye izin vererek API daha güvenli değildir.
    • CORS'yi zorunlu kılmak istemciye (tarayıcıya) bağlı. Sunucu isteği yürütür ve yanıtı döndürür; hata döndüren ve yanıtı engelleyen istemcidir. Örneğin, aşağıdaki araçlardan herhangi biri sunucu yanıtını görüntüler:
  • Bu, bir sunucunun tarayıcıların normalde yasak olacak farklı bir origin’e yönelik XHR veya Fetch API isteği yürütmesine izin vermesinin bir yoludur.
    • CORS'siz tarayıcılar çıkış noktaları arası istekler yapamaz. CORS'ye başlamadan önce, bu kısıtlamayı aşmak için JSONP kullanıldı. JSONP XHR kullanmaz, yanıtı almak için etiketini kullanır <script> . Betiklerin farklı kaynaklardan yüklenmesine izin verilir.

CORS belirtimi, çıkış noktaları arası istekleri etkinleştiren birkaç yeni HTTP üst bilgisi kullanıma sunulmuştur. Tarayıcı CORS'yi destekliyorsa çıkış noktaları arası istekler için bu üst bilgileri otomatik olarak ayarlar. CORS'yi etkinleştirmek için özel JavaScript kodu gerekmez.

Dağıtılan örnekte PUT test düğmesini seçin. Origin başlığı:

  • İstekte bulunan sitenin etki alanını sağlar.
  • Zorunludur ve ana bilgisayardan farklı olmalıdır.

Genel üst bilgiler

Request URL: https://cors1.azurewebsites.net/api/values
Request Method: GET
Status Code: 200 OK

Yanıt üst bilgileri

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

İstek üst bilgileri

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 ...

OPTIONS isteklerinde sunucu, yanıtta Yanıt üst bilgileriAccess-Control-Allow-Origin: {allowed origin} üst bilgisini ayarlar. Örneğin, örnek kodda Delete [EnableCors] düğme OPTIONS isteği aşağıdaki üst bilgileri içerir:

Genel üst bilgiler

Request URL: https://cors3.azurewebsites.net/api/TodoItems2/MyDelete2/5
Request Method: OPTIONS
Status Code: 204 No Content

Yanıt üst bilgileri

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

İstek üst bilgileri

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

Yukarıdaki Yanıt üst bilgilerinde, sunucu yanıttaki Access-Control-Allow-Origin üst bilgisini ayarlar. https://cors1.azurewebsites.net Bu üst bilginin değeri istekten alınan Origin üst bilgiyle eşleşir.

AllowAnyOrigin çağrılırsa, joker karakter değeri olan Access-Control-Allow-Origin: * döndürülür. AllowAnyOrigin herhangi bir çıkış noktası sağlar.

Yanıt Access-Control-Allow-Origin başlığını içermiyorsa, kaynaklar arası istek başarısız olur. Özellikle, tarayıcı isteğe izin vermemektedir. Sunucu başarılı bir yanıt döndürse bile, tarayıcı yanıtı istemci uygulaması için kullanılabilir hale getirmez.

HTTP'den HTTPS'ye yönlendirme, CORS ön kontrol isteğinde ERR_INVALID_REDIRECT hatasına neden olur

UseHttpsRedirection tarafından HTTPS'ye yönlendirilen, HTTP kullanan bir uç noktaya yapılan istekler ERR_INVALID_REDIRECT on the CORS preflight request ile başarısız olur.

API projeleri, istekleri HTTPS'ye yeniden yönlendirmek için kullanmak UseHttpsRedirection yerine HTTP isteklerini reddedebilir.

IIS'de CORS

IIS'ye dağıtım yaparken, sunucu anonim erişime izin verecek şekilde yapılandırılmamışsa CORS'nin Windows Kimlik Doğrulamasından önce çalışması gerekir. Bu senaryoyu desteklemek için IIS CORS modülünün uygulama için yüklenmesi ve yapılandırılması gerekir.

CORS'i test edin

Örnek indirmede CORS'yi test etmek için kod bulunur. İndirmeyi öğrenin. Örnek, Razor Pages eklenmiş bir API projesidir:

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();

Warning

WithOrigins("https://localhost:<port>");yalnızca indirme örnek koduna benzer bir örnek uygulamayı test etmek için kullanılmalıdır.

Aşağıdaki ValuesController, test etmek için uç noktaları sunar:

[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, Rick.Docs.Samples.RouteInfo NuGet paketi tarafından sağlanır ve yol bilgilerini görüntüler.

Aşağıdaki yaklaşımlardan birini kullanarak yukarıdaki örnek kodu test edin:

  • Örneği, dotnet run varsayılan URL’sini kullanarak https://localhost:5001 ile çalıştırın.
  • URL’si https://localhost:44398 olan örneği, bağlantı noktası 44398 olarak ayarlanmış şekilde Visual Studio’dan çalıştırın.

F12 araçlarıyla tarayıcı kullanma:

  • Değerler düğmesini seçin ve Ağ sekmesindeki üst bilgileri gözden geçirin.

  • PUT test düğmesini seçin. OPTIONS isteğinin nasıl görüntüleneceğine ilişkin yönergeler için OPTIONS isteklerini görüntüleme bölümüne bakın. PUT testi iki istek oluşturur: OPTIONS ön uçuş isteği ve PUT isteği.

  • GetValues2 [DisableCors] Başarısız bir CORS isteğini tetikleme düğmesini seçin. Belgede belirtildiği gibi yanıt 200 başarı döndürür, ancak CORS isteği yapılmaz. CORS hatasını görmek için Konsol sekmesini seçin. Tarayıcıya bağlı olarak, aşağıdakine benzer bir hata görüntülenir:

    'https://cors1.azurewebsites.net/api/values/GetValues2' origin’inden 'https://cors3.azurewebsites.net' konumundaki kaynağa erişim CORS ilkesi tarafından engellendi: İstenen kaynakta 'Access-Control-Allow-Origin' üst bilgisi bulunmuyor. Opak yanıt gereksinimlerinize uygunsa, CORS devre dışı bırakılmış olan kaynağı getirmek için isteğin modunu 'cors yok' olarak ayarlayın.

CORS özellikli uç noktalar curl veya Fiddler gibi bir araçla test edilebilir. Bir araç kullanılırken, Origin üst bilgisinde belirtilen isteğin kaynağı, isteği alan ana bilgisayardan farklı olmalıdır. İstek, üst bilgisinin değerine göre Origin değilse:

  • CORS ara yazılımının isteği işlemesine gerek yoktur.
  • CORS başlıkları yanıtta döndürülmüyor.

Aşağıdaki komut, bilgi içeren bir OPTIONS isteği göndermek için kullanır curl :

curl -X OPTIONS https://cors3.azurewebsites.net/api/TodoItems2/5 -i

CORS'yi [EnableCors] özniteliği ve RequireCors yöntemiyle test edin

uç nokta yönlendirmesini kullanarak CORS'yi her bir uç nokta için etkinleştiren RequireCors aşağıdaki kodu göz önünde bulundurun:

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();

Yalnızca /echo uç noktasının, belirtilen ilkeyi kullanarak kaynaklar arası isteklere izin vermek için RequireCors kullandığına dikkat edin. Aşağıdaki denetleyiciler [EnableCors] özniteliğini kullanarak CORS'yi etkinleştirir.

Aşağıdaki TodoItems1Controller test amaçlı uç noktalar sağlar:

[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);
}

Delete [EnableCors] ve GET [EnableCors] düğmeleri başarılı olur, çünkü uç noktalarında [EnableCors] bulunur ve preflight isteklerine yanıt verirler. Diğer uç noktalar başarısız olur. JavaScript şunları gönderdiğinden GET düğmesi başarısız oluyor:

 headers: {
      "Content-Type": "x-custom-header"
 },

Aşağıdakiler TodoItems2Controller benzer uç noktalar sağlar, ancak SEÇENEKLER isteklerine yanıt vermek için açık kod içerir:

[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);
}

Yukarıdaki kod, örneği Azure'da dağıtarak test edilebilir. Denetleyici açılır listesinde Preflight'ı ve ardından Denetleyiciyi Ayarla'yı seçin. Uç noktalara yapılan TodoItems2Controller tüm CORS çağrıları başarılı olur.

Ek kaynaklar

Yayımlayanlar Rick Anderson ve Kirk Larkin

Bu makalede, ASP.NET Core uygulamasında CORS'nin nasıl etkinleştirileceği gösterilmektedir.

Tarayıcı güvenliği, bir web sayfasının web sayfasına hizmet verenden farklı bir etki alanına istekte bulunmasını engeller. Bu kısıtlama aynı çıkış noktası ilkesi olarak adlandırılır. Aynı çıkış noktası ilkesi, kötü amaçlı bir sitenin başka bir siteden hassas verileri okumasını önler. Bazen başka sitelerin uygulamanıza çıkış noktaları arası isteklerde bulunmasına izin vermek isteyebilirsiniz. Daha fazla bilgi için Mozilla CORS makalesine bakın.

Çıkış Noktaları Arası Kaynak Paylaşımı (CORS):

  • Bir sunucunun aynı kaynak ilkesini gevşetmesini sağlayan bir W3C standardıdır.
  • Bir güvenlik özelliği değildir , CORS güvenliği rahatlatır. CORS'ye izin vererek API daha güvenli değildir. Daha fazla bilgi için bkz . CORS nasıl çalışır?
  • Bir sunucunun bazı çıkış noktaları arası isteklere izin verirken diğerlerini reddetmesine izin verir.
  • JSONP gibi önceki tekniklerden daha güvenli ve daha esnektir.

Örnek kodu görüntüleme veya indirme (indirme)

Aynı kaynak

Aynı şemalara, konaklara ve bağlantı noktalarına sahip olan iki URL'nin kaynağı aynıdır (RFC 6454).

Bu iki URL'nin kaynağı aynıdır:

  • https://example.com/foo.html
  • https://example.com/bar.html

Bu URL'lerin çıkış noktaları önceki iki URL'den farklı:

  • https://example.net: Farklı alan adı
  • https://www.example.com/foo.html: Farklı alt alan adı
  • http://example.com/foo.html: Farklı düzen
  • https://example.com:9000/foo.html: Farklı bağlantı noktası

CORS'yi etkinleştirme

CORS'yi etkinleştirmenin üç yolu vardır:

[EnableCors] özniteliğini adlandırılmış bir ilkeyle kullanmak, CORS'yi destekleyen uç noktaları sınırlama konusunda en iyi denetimi sağlar.

Warning

UseCors doğru sırada çağrılmalıdır. Daha fazla bilgi için bkz. Ara katman sırası. Örneğin, UseCors kullanılırken UseResponseCachingönce UseResponseCaching çağrılmalıdır.

Her yaklaşım aşağıdaki bölümlerde ayrıntılı olarak anlatılır.

Adlandırılmış ilke ve ara yazılım ile CORS

CORS ara yazılımı çıkış noktaları arası istekleri işler. Aşağıdaki kod, belirtilen kaynaklarla uygulamanın tüm uç noktalarına bir CORS ilkesi uygular:

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();

Yukarıdaki kod:

Uç nokta yönlendirmesinde, CORS ara yazılımı, ile UseRouting çağrıları arasında çalışacak şekilde yapılandırılUseEndpoints.

Yöntem çağrısı, AddCors CORS hizmetlerini uygulamanın hizmet kapsayıcısına ekler:

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();

Daha fazla bilgi için bu belgedeki CORS ilkesi seçeneklerine bakın.

Yöntemler CorsPolicyBuilder , aşağıdaki kodda gösterildiği gibi zincirlenebilir:

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();

Not: Belirtilen URL sonunda eğik çizgi () içermemelidir./ URL / ile bitiyorsa, karşılaştırma false döndürür ve hiçbir başlık döndürülmez.

Warning

UseCors, UseRouting öğesinden sonra ve UseAuthorization öğesinden önce yerleştirilmelidir. Bu, CORS üst bilgilerinin hem yetkili hem de yetkisiz çağrılar için yanıta dahil edilmesini sağlamaktır.

UseCors ve UseStaticFiles sırası

Genellikle, UseStaticFiles, UseCors'den önce çağrılır. Siteler arası statik dosyaları almak için JavaScript kullanan uygulamaların, UseCors işleminden önce UseStaticFiles çağrısını yapması gerekir.

Varsayılan ilke ve ara yazılım ile CORS

Aşağıdaki vurgulanmış kod, varsayılan CORS ilkesini etkinleştirir:

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();

Yukarıdaki kod, varsayılan CORS ilkesini tüm denetleyici uç noktalarına uygular.

Uç nokta yönlendirmesi ile Cors'i etkinleştirme

kullanarak RequireCorsCORS'nin uç nokta başına etkinleştirilmesi otomatik denetim öncesi istekleri desteklemez. Daha fazla bilgi için bu GitHub sorununa bakın ve CORS'yi uç nokta yönlendirme ve [HttpOptions] ile test edin.

Uç nokta yönlendirme ile CORS, uzantı yöntemleri kümesi kullanılarak RequireCors uç nokta temelinde etkinleştirilebilir:

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();

Önceki kodda:

  • app.UseCors CORS ara yazılımını etkinleştirir. Varsayılan ilke yapılandırılmadığından tek app.UseCors() başına CORS'yi etkinleştirmez.
  • /echo ve denetleyici uç noktaları, belirtilen ilkeyi kullanarak çıkış noktaları arası isteklere izin verir.
  • Varsayılan bir ilke belirtilmediğinden, /echo2 ve Razor Pages uç noktaları kaynaklar arası isteklere izin vermez.

[DisableCors] özniteliği ile uç nokta yönlendirmesi tarafından etkinleştirilen CORS'yi devre dışı bırakmazRequireCors.

Yukarıdakine benzer bir kodu test etme yönergeleri için bkz . Uç nokta yönlendirme ve [HttpOptions] ile CORS'yi test etme.

CorS'yi özniteliklerle etkinleştirme

CORS'yi [EnableCors] özniteliğiyle etkinleştirmek ve yalnızca CORS gerektiren uç noktalara adlandırılmış bir ilke uygulamak en iyi denetimi sağlar.

[EnableCors] özniteliği, CORS'yi genel olarak uygulamaya bir alternatif sağlar. [EnableCors] özniteliği, tüm uç noktalar yerine seçili uç noktalar için CORS'yi etkinleştirir:

  • [EnableCors] varsayılan ilkeyi belirtir.
  • [EnableCors("{Policy String}")] adlandırılmış bir ilke belirtir.

[EnableCors] Özniteliği şu özelliklere uygulanabilir:

  • Razor Sayfa PageModel
  • Controller
  • Denetleyici eylem yöntemi

[EnableCors] özniteliğiyle denetleyicilere, sayfa modellerine veya eylem yöntemlerine farklı ilkeler uygulanabilir. [EnableCors] Öznitelik bir denetleyiciye, sayfa modeline veya eylem yöntemine uygulandığında ve ara yazılımda CORS etkinleştirildiğinde, her iki ilke de uygulanır. İlkeleri birleştirmenizi önermiyoruz. Şunu kullanın [EnableCors] öznitelik veya ara yazılım, aynı uygulamada ikisi birden değil.

Aşağıdaki kod her yönteme farklı bir ilke uygular:

[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(),
        };
    }
}

Aşağıdaki kod iki CORS ilkesi oluşturur:

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();

CORS isteklerini sınırlamanın en iyi denetimi için:

  • [EnableCors("MyPolicy")] öğesini adlandırılmış bir ilkeyle kullanın.
  • Varsayılan bir ilke tanımlamayın.
  • Uç nokta yönlendirme kullanmayın.

Sonraki bölümdeki kod önceki listeyi karşılar.

CORS'yi devre dışı bırakma

[DisableCors] özniteliği, uç nokta yönlendirmesi tarafından etkinleştirilen CORS'yi devre dışı bırakmaz.

Aşağıdaki kod CORS ilkesini "MyPolicy"tanımlar:

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();

Aşağıdaki kod, GetValues2 eylemi için CORS’u devre dışı bırakır:

[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();

}

Yukarıdaki kod:

  • Uç nokta yönlendirme ile CORS'yi etkinleştirmez.
  • Varsayılan bir CORS ilkesi tanımlamaz.
  • Denetleyici için CORS ilkesini etkinleştirmek üzere "MyPolicy" kullanır.
  • GetValues2 yöntemi için CORS’u devre dışı bırakır.

Önceki kodu test etmeye ilişkin yönergeler için CORS'u Test Etme bölümüne bakın.

CORS ilke seçenekleri

Bu bölümde, CORS ilkesinde ayarlanabilecek çeşitli seçenekler açıklanmaktadır:

AddPolicy içinde Program.cs çağrılır. Bazı seçenekler için öncelikle CORS'nin çalışma şekli bölümünü okumak yararlı olabilir.

İzin verilen çıkış noktalarını ayarlama

AllowAnyOrigin: Herhangi bir şema (http veya https) ile tüm kaynaklardan GELEN CORS isteklerine izin verir. AllowAnyOrigin güvenli değildir çünkü herhangi bir web sitesi uygulamaya çıkış noktaları arası isteklerde bulunabilir.

Note

AllowAnyOrigin ve AllowCredentials değerlerinin belirtilmesi güvenli olmayan bir yapılandırmadır ve siteler arası istek sahteciliğine neden olabilir. Bir uygulama her iki yöntemle de yapılandırıldığında CORS hizmeti geçersiz bir CORS yanıtı döndürür.

AllowAnyOrigin, ön kontrol isteklerini ve Access-Control-Allow-Origin üst bilgisini etkiler. Daha fazla bilgi için Ön kontrol istekleri adlı bölüme bakın.

SetIsOriginAllowedToAllowWildcardSubdomains: İlkenin IsOriginAllowed özelliğini, kaynağın izin verilip verilmediğini değerlendirirken çıkış noktalarının yapılandırılmış joker karakter etki alanıyla eşleşmesini sağlayan bir işlev olacak şekilde ayarlar.

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();

Önceki kodda SetIsOriginAllowedToAllowWildcardSubdomains, joker kökeni "https://*.example.com" ile çağrılır. Bu yapılandırma, example.com gibi https://subdomain.example.com veya https://api.example.com alt etki alanlarından gelen CORS isteklerine izin verir. * Joker karakterin alt etki alanı eşleştirmeyi etkinleştirmek için kaynağa eklenmesi gerekir.

İzin verilen HTTP yöntemlerini ayarlama

AllowAnyMethod:

  • Herhangi bir HTTP yöntemine izin verir:
  • Ön kontrol isteklerini ve Access-Control-Allow-Methods üst bilgisini etkiler. Daha fazla bilgi için Ön kontrol istekleri adlı bölüme bakın.

İzin verilen istek üst bilgilerini ayarlayın

Bir CORS isteğinde yazar tanımlı istek üst bilgilerinin gönderilmesine izin vermek için WithHeaders çağrısını yapın ve izin verilen üst bilgileri belirtin:

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();

Tüm author istek üst bilgilerine izin vermek için AllowAnyHeader çağırın:

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 preflight isteklerini ve Access-Control-Request-Headers üst bilgisini etkiler. Daha fazla bilgi için Ön kontrol istekleri adlı bölüme bakın.

WithHeaders tarafından belirtilen belirli üstbilgilerle eşleşen bir CORS ara yazılım ilkesi, yalnızca Access-Control-Request-Headers içinde gönderilen üstbilgiler WithHeaders içinde belirtilen üstbilgilerle tam olarak eşleştiğinde mümkündür.

Örneğin, aşağıdaki gibi yapılandırılmış bir uygulamayı göz önünde bulundurun:

app.UseCors(policy => policy.WithHeaders(HeaderNames.CacheControl));

CORS ara yazılımı, Content-Language (HeaderNames.ContentLanguage) WithHeaders içinde listelenmediği için aşağıdaki istek üst bilgisine sahip bir ön kontrol isteğini reddeder:

Access-Control-Request-Headers: Cache-Control, Content-Language

Uygulama 200 Tamam yanıtı döndürür ancak CORS üst bilgilerini geri göndermez. Bu nedenle tarayıcı çıkış noktaları arası isteği denemez.

Erişime açılan yanıt başlıklarını ayarlayın

Varsayılan olarak, tarayıcı tüm yanıt üst bilgilerini uygulamaya sunmaz. Daha fazla bilgi için bkz . W3C Çıkış Noktaları Arası Kaynak Paylaşımı (Terminoloji): Basit Yanıt Üst Bilgisi.

Varsayılan olarak kullanılabilen yanıt üst bilgileri şunlardır:

  • Cache-Control
  • Content-Language
  • Content-Type
  • Expires
  • Last-Modified
  • Pragma

CORS belirtimi bu üst bilgileri basit yanıt üst bilgilerini çağırır. Diğer üst bilgileri uygulamanın kullanımına sunmak için WithExposedHeaders çağrısı yapın:

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();

Kaynaklar arası isteklerde kimlik bilgileri

Kimlik bilgileri, bir CORS isteğinde özel olarak ele alınmalıdır. Varsayılan olarak, tarayıcı çıkış noktaları arası bir istekle kimlik bilgileri göndermez. Kimlik bilgileri, tanımlama bilgilerini ve HTTP kimlik doğrulama şemalarını içerir. Farklı kaynaklar arası bir istekle kimlik bilgilerini göndermek için istemci, XMLHttpRequest.withCredentials değerini true olarak ayarlamalıdır.

XMLHttpRequest doğrudan kullanımı:

var xhr = new XMLHttpRequest();
xhr.open('get', 'https://www.example.com/api/test');
xhr.withCredentials = true;

jQuery kullanma:

$.ajax({
  type: 'get',
  url: 'https://www.example.com/api/test',
  xhrFields: {
    withCredentials: true
  }
});

Fetch API'sini kullanma:

fetch('https://www.example.com/api/test', {
    credentials: 'include'
});

Sunucunun kimlik bilgilerine izin vermesi gerekir. Kaynaklar arası kimlik bilgilerine izin vermek için AllowCredentials çağırın:

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();

HTTP yanıtı, sunucunun kaynaklar arası bir istekte kimlik bilgilerine izin verdiğini tarayıcıya bildiren bir Access-Control-Allow-Credentials üst bilgisi içerir.

Tarayıcı kimlik bilgilerini gönderir ancak yanıt geçerli bir Access-Control-Allow-Credentials başlığı içermiyorsa, tarayıcı yanıtı uygulamanın erişimine açmaz ve kaynaklar arası istek başarısız olur.

Kaynaklar arası kimlik bilgilerine izin vermek güvenlik riskidir. Başka bir etki alanındaki bir web sitesi, kullanıcının bilgisi olmadan oturum açmış bir kullanıcının kimlik bilgilerini kullanıcı adına uygulamaya gönderebilir.

CORS belirtimi ayrıca, "*" üstbilgisi mevcutsa kaynakların Access-Control-Allow-Credentials (tüm kaynaklar) olarak ayarlanmasının geçersiz olduğunu belirtir.

Ön kontrol istekleri

Bazı CORS istekleri için tarayıcı, gerçek isteği yapmadan önce ek bir OPTIONS isteği gönderir. Bu istek, ön kontrol isteği olarak adlandırılır. Tarayıcı, aşağıdaki koşulların tümü doğruysa ön kontrol isteğini atlayabilir:

  • İstek yöntemi GET, HEAD veya POST şeklindedir.
  • Uygulama, Accept, Accept-Language, Content-Language, Content-Type veya Last-Event-ID dışında istek üst bilgileri ayarlamaz.
  • Content-Type Üst bilgi ayarlanırsa aşağıdaki değerlerden birine sahiptir:
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain

İstemci isteği için ayarlanan istek üst bilgilerine ilişkin kural, uygulamanın setRequestHeader nesnesi üzerinde XMLHttpRequest çağrısı yaparak ayarladığı üst bilgiler için geçerlidir. CORS spesifikasyonu bu üst bilgileri yazar istek üst bilgileri olarak adlandırır. Kural, tarayıcının ayarlayabileceğiniz , User-Agentveya Hostgibi Content-Lengthüst bilgiler için geçerli değildir.

Aşağıda, bu belgenin Test CORS bölümündeki [Test et] düğmesinden yapılan denetim öncesi isteğine benzer bir örnek yanıt verilmiştir.

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

Ön kontrol isteği, HTTP OPTIONS yöntemini kullanır. Aşağıdaki üst bilgileri içerebilir:

Ön kontrol isteği reddedilirse uygulama 200 OK yanıtı döndürür, ancak CORS başlıklarını ayarlamaz. Bu nedenle tarayıcı çıkış noktaları arası isteği denemez. Reddedilmiş bir preflight isteği örneğini görmek için bu belgedeki CORS’yi Test Et bölümüne bakın.

F12 araçlarını kullanarak, konsol uygulaması tarayıcıya bağlı olarak aşağıdakilerden birine benzer bir hata gösterir:

  • Firefox: Çapraz Kaynak İsteği Engellendi: Aynı Kaynak İlkesi, https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5 konumundaki uzak kaynağın okunmasına izin vermiyor. (Neden: CORS isteği başarılı olmadı). Daha fazla bilgi edinin
  • Chromium tabanlı: 'https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5' kaynağından 'https://cors3.azurewebsites.net' konumuna getirme erişimi CORS ilkesi tarafından engellendi: Ön kontrol isteğine verilen yanıt, erişim denetimi kontrolünden geçmiyor: İstenen kaynakta 'Access-Control-Allow-Origin' üst bilgisi bulunmuyor. Opak yanıt gereksinimlerinize uygunsa, CORS devre dışı bırakılmış olan kaynağı getirmek için isteğin modunu 'cors yok' olarak ayarlayın.

Belirli üstbilgilere izin vermek için WithHeaders çağrısını yapın:

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();

Tüm author istek üst bilgilerine izin vermek için AllowAnyHeader çağırın:

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();

Tarayıcılar, Access-Control-Request-Headers öğesini nasıl ayarladıkları konusunda tutarlı değildir. Aşağıdakilerden biri varsa:

  • Üstbilgiler, "*" dışında herhangi bir değere ayarlanır
  • AllowAnyHeader çağrılır: En az Accept, Content-Typeve Originile birlikte, desteklemek istediğiniz özel üst bilgileri ekleyin.

Otomatik ön kontrol isteği kodu

CORS ilkesi aşağıdakilerden biri uygulandığında:

  • app.UseCors içinde Program.cs çağrısı yaparak genel olarak.
  • özniteliğini [EnableCors] kullanma.

ASP.NET Core, denetim öncesi SEÇENEKLER isteğine yanıt verir.

RequireCors kullanılarak CORS'nin uç nokta bazında etkinleştirilmesi şu anda otomatik ön kontrol isteklerini desteklemez.

Bu belgenin Test CORS bölümünde bu davranış gösterilmektedir.

Preflight istekleri için [HttpOptions] özniteliği

CORS uygun ilkeyle etkinleştirildiğinde, ASP.NET Core genellikle CORS denetim öncesi isteklerine otomatik olarak yanıt verir. Bazı senaryolarda bu durum söz konusu olmayabilir. Örneğin, uç nokta yönlendirme ile CORS kullanma.

Aşağıdaki kod, OPTIONS istekleri için uç noktalar oluşturmak için [HttpOptions] özniteliğini kullanır:

[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);
    }

Yukarıdaki kodu test etme yönergeleri için Uç nokta yönlendirmesi ve [HttpOptions] ile CORS'yi test etme bölümüne bkz.

Denetim öncesi süre sonu süresini ayarlama

Access-Control-Max-Age üst bilgisi, preflight isteğine verilen yanıtın ne kadar süreyle önbellekte tutulabileceğini belirtir. Bu üst bilgiyi ayarlamak için SetPreflightMaxAge çağrısını yapın:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCors(options =>
{
    options.AddPolicy("MySetPreflightExpirationPolicy",
        policy =>
        {
            policy.WithOrigins("http://example.com")
                   .SetPreflightMaxAge(TimeSpan.FromSeconds(2520));
        });
});

builder.Services.AddControllers();

var app = builder.Build();

CORS nasıl çalışır?

Bu bölüm, HTTP iletileri düzeyinde bir CORS isteğinde neler olduğunu açıklar.

  • CORS bir güvenlik özelliği değildir . CORS, bir sunucunun aynı kaynak ilkesini gevşetmesini sağlayan bir W3C standardıdır.
  • CORS'ye izin vererek API daha güvenli değildir.
    • CORS'yi zorunlu kılmak istemciye (tarayıcıya) bağlı. Sunucu isteği yürütür ve yanıtı döndürür; hata döndüren ve yanıtı engelleyen istemcidir. Örneğin, aşağıdaki araçlardan herhangi biri sunucu yanıtını görüntüler:
  • Bu, bir sunucunun tarayıcıların normalde yasak olacak farklı bir origin’e yönelik XHR veya Fetch API isteği yürütmesine izin vermesinin bir yoludur.
    • CORS'siz tarayıcılar çıkış noktaları arası istekler yapamaz. CORS'ye başlamadan önce, bu kısıtlamayı aşmak için JSONP kullanıldı. JSONP XHR kullanmaz, yanıtı almak için etiketini kullanır <script> . Betiklerin farklı kaynaklardan yüklenmesine izin verilir.

CORS belirtimi, çıkış noktaları arası istekleri etkinleştiren birkaç yeni HTTP üst bilgisi kullanıma sunulmuştur. Tarayıcı CORS'yi destekliyorsa çıkış noktaları arası istekler için bu üst bilgileri otomatik olarak ayarlar. CORS'yi etkinleştirmek için özel JavaScript kodu gerekmez.

Aşağıda, Değerler test düğmesinden https://cors1.azurewebsites.net/api/values konumuna yapılan farklı kaynaktan gelen bir isteğin örneği verilmiştir. Origin başlığı:

  • İstekte bulunan sitenin etki alanını sağlar.
  • Zorunludur ve ana bilgisayardan farklı olmalıdır.

Genel üst bilgiler

Request URL: https://cors1.azurewebsites.net/api/values
Request Method: GET
Status Code: 200 OK

Yanıt üst bilgileri

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

İstek üst bilgileri

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 ...

OPTIONS isteklerinde sunucu, yanıtta Yanıt üst bilgileriAccess-Control-Allow-Origin: {allowed origin} üst bilgisini ayarlar. Örneğin, dağıtılan örnek, Sil düğmesi OPTIONS isteği aşağıdaki üst bilgileri içerir:

Genel üst bilgiler

Request URL: https://cors3.azurewebsites.net/api/TodoItems2/MyDelete2/5
Request Method: OPTIONS
Status Code: 204 No Content

Yanıt üst bilgileri

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

İstek üst bilgileri

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

Yukarıdaki Yanıt üst bilgilerinde, sunucu yanıttaki Access-Control-Allow-Origin üst bilgisini ayarlar. https://cors1.azurewebsites.net Bu üst bilginin değeri istekten alınan Origin üst bilgiyle eşleşir.

AllowAnyOrigin çağrılırsa, joker karakter değeri olan Access-Control-Allow-Origin: * döndürülür. AllowAnyOrigin herhangi bir çıkış noktası sağlar.

Yanıt Access-Control-Allow-Origin başlığını içermiyorsa, kaynaklar arası istek başarısız olur. Özellikle, tarayıcı isteğe izin vermemektedir. Sunucu başarılı bir yanıt döndürse bile, tarayıcı yanıtı istemci uygulaması için kullanılabilir hale getirmez.

HTTP'den HTTPS'ye yönlendirme, CORS ön kontrol isteğinde ERR_INVALID_REDIRECT hatasına neden olur

UseHttpsRedirection tarafından HTTPS'ye yönlendirilen, HTTP kullanan bir uç noktaya yapılan istekler ERR_INVALID_REDIRECT on the CORS preflight request ile başarısız olur.

API projeleri, istekleri HTTPS'ye yeniden yönlendirmek için kullanmak UseHttpsRedirection yerine HTTP isteklerini reddedebilir.

SEÇENEKLER isteklerini görüntüleme

Varsayılan olarak, Chrome ve Edge tarayıcıları F12 araçlarının ağ sekmesinde SEÇENEKLER isteklerini göstermez. SEÇENEKLER isteklerini bu tarayıcılarda görüntülemek için:

  • chrome://flags/#out-of-blink-cors veya edge://flags/#out-of-blink-cors
  • bayrağını devre dışı bırakın.
  • restart.

Firefox, SEÇENEKLER isteklerini varsayılan olarak gösterir.

IIS'de CORS

IIS'ye dağıtım yaparken, sunucu anonim erişime izin verecek şekilde yapılandırılmamışsa CORS'nin Windows Kimlik Doğrulamasından önce çalışması gerekir. Bu senaryoyu desteklemek için IIS CORS modülünün uygulama için yüklenmesi ve yapılandırılması gerekir.

CORS'i test edin

Örnek indirmede CORS'yi test etmek için kod bulunur. İndirmeyi öğrenin. Örnek, Razor Pages eklenmiş bir API projesidir:

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();

Warning

WithOrigins("https://localhost:<port>");yalnızca indirme örnek koduna benzer bir örnek uygulamayı test etmek için kullanılmalıdır.

Aşağıdaki ValuesController, test etmek için uç noktaları sunar:

[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, Rick.Docs.Samples.RouteInfo NuGet paketi tarafından sağlanır ve yol bilgilerini görüntüler.

Aşağıdaki yaklaşımlardan birini kullanarak yukarıdaki örnek kodu test edin:

  • Örneği, dotnet run varsayılan URL’sini kullanarak https://localhost:5001 ile çalıştırın.
  • URL’si https://localhost:44398 olan örneği, bağlantı noktası 44398 olarak ayarlanmış şekilde Visual Studio’dan çalıştırın.

F12 araçlarıyla tarayıcı kullanma:

  • Değerler düğmesini seçin ve Ağ sekmesindeki üst bilgileri gözden geçirin.

  • PUT test düğmesini seçin. OPTIONS isteğinin nasıl görüntüleneceğine ilişkin yönergeler için OPTIONS isteklerini görüntüleme bölümüne bakın. PUT testi iki istek oluşturur: OPTIONS ön uçuş isteği ve PUT isteği.

  • GetValues2 [DisableCors] Başarısız bir CORS isteğini tetikleme düğmesini seçin. Belgede belirtildiği gibi yanıt 200 başarı döndürür, ancak CORS isteği yapılmaz. CORS hatasını görmek için Konsol sekmesini seçin. Tarayıcıya bağlı olarak, aşağıdakine benzer bir hata görüntülenir:

    'https://cors1.azurewebsites.net/api/values/GetValues2' origin’inden 'https://cors3.azurewebsites.net' konumundaki kaynağa erişim CORS ilkesi tarafından engellendi: İstenen kaynakta 'Access-Control-Allow-Origin' üst bilgisi bulunmuyor. Opak yanıt gereksinimlerinize uygunsa, CORS devre dışı bırakılmış olan kaynağı getirmek için isteğin modunu 'cors yok' olarak ayarlayın.

CORS özellikli uç noktalar curl veya Fiddler gibi bir araçla test edilebilir. Bir araç kullanılırken, Origin üst bilgisinde belirtilen isteğin kaynağı, isteği alan ana bilgisayardan farklı olmalıdır. İstek, üst bilgisinin değerine göre Origin değilse:

  • CORS ara yazılımının isteği işlemesine gerek yoktur.
  • CORS başlıkları yanıtta döndürülmüyor.

Aşağıdaki komut, bilgi içeren bir OPTIONS isteği göndermek için kullanır curl :

curl -X OPTIONS https://cors3.azurewebsites.net/api/TodoItems2/5 -i

Uç nokta yönlendirme ve [HttpOptions] ile CORS'i test edin

RequireCors kullanılarak uç nokta bazında CORS'un etkinleştirilmesi şu anda otomatik preflight isteklerini desteklemez. CORS'yi etkinleştirmek için uç nokta yönlendirmesini kullanan aşağıdaki kodu göz önünde bulundurun:

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();

Aşağıdaki TodoItems1Controller test amaçlı uç noktalar sağlar:

[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);
}

Dağıtıma alınmış https://cors1.azurewebsites.net/test?number=1test sayfasından yukarıdaki kodu test edin.

Delete [EnableCors] ve GET [EnableCors] düğmeleri başarılı olur, çünkü uç noktalarında [EnableCors] bulunur ve preflight isteklerine yanıt verirler. Diğer uç noktalar başarısız olur. JavaScript şunları gönderdiğinden GET düğmesi başarısız oluyor:

 headers: {
      "Content-Type": "x-custom-header"
 },

Aşağıdakiler TodoItems2Controller benzer uç noktalar sağlar, ancak SEÇENEKLER isteklerine yanıt vermek için açık kod içerir:

[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);
}

Yukarıdaki kod, örneği Azure'da dağıtarak test edilebilir. Denetleyici açılır listesinde Preflight'ı ve ardından Denetleyiciyi Ayarla'yı seçin. Uç noktalara yapılan TodoItems2Controller tüm CORS çağrıları başarılı olur.

Ek kaynaklar

Yayımlayanlar Rick Anderson ve Kirk Larkin

Bu makalede, ASP.NET Core uygulamasında CORS'nin nasıl etkinleştirileceği gösterilmektedir.

Tarayıcı güvenliği, bir web sayfasının web sayfasına hizmet verenden farklı bir etki alanına istekte bulunmasını engeller. Bu kısıtlama aynı çıkış noktası ilkesi olarak adlandırılır. Aynı çıkış noktası ilkesi, kötü amaçlı bir sitenin başka bir siteden hassas verileri okumasını önler. Bazen başka sitelerin uygulamanıza çıkış noktaları arası isteklerde bulunmasına izin vermek isteyebilirsiniz. Daha fazla bilgi için Mozilla CORS makalesine bakın.

Çıkış Noktaları Arası Kaynak Paylaşımı (CORS):

  • Bir sunucunun aynı kaynak ilkesini gevşetmesini sağlayan bir W3C standardıdır.
  • Bir güvenlik özelliği değildir , CORS güvenliği rahatlatır. CORS'ye izin vererek API daha güvenli değildir. Daha fazla bilgi için bkz . CORS nasıl çalışır?
  • Bir sunucunun bazı çıkış noktaları arası isteklere izin verirken diğerlerini reddetmesine izin verir.
  • JSONP gibi önceki tekniklerden daha güvenli ve daha esnektir.

Örnek kodu görüntüleme veya indirme (indirme)

Aynı kaynak

Aynı şemalara, konaklara ve bağlantı noktalarına sahip olan iki URL'nin kaynağı aynıdır (RFC 6454).

Bu iki URL'nin kaynağı aynıdır:

  • https://example.com/foo.html
  • https://example.com/bar.html

Bu URL'lerin çıkış noktaları önceki iki URL'den farklı:

  • https://example.net: Farklı alan adı
  • https://www.example.com/foo.html: Farklı alt alan adı
  • http://example.com/foo.html: Farklı düzen
  • https://example.com:9000/foo.html: Farklı bağlantı noktası

CORS'yi etkinleştirme

CORS'yi etkinleştirmenin üç yolu vardır:

[EnableCors] özniteliğini adlandırılmış bir ilkeyle kullanmak, CORS'yi destekleyen uç noktaları sınırlama konusunda en iyi denetimi sağlar.

Warning

UseCors doğru sırada çağrılmalıdır. Daha fazla bilgi için bkz. Ara katman sırası. Örneğin, UseCors kullanılırken UseResponseCachingönce UseResponseCaching çağrılmalıdır.

Her yaklaşım aşağıdaki bölümlerde ayrıntılı olarak anlatılır.

Adlandırılmış ilke ve ara yazılım ile CORS

CORS ara yazılımı çıkış noktaları arası istekleri işler. Aşağıdaki kod, belirtilen kaynaklarla uygulamanın tüm uç noktalarına bir CORS ilkesi uygular:

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();
        });
    }
}

Yukarıdaki kod:

Uç nokta yönlendirmesinde, CORS ara yazılımı, ile UseRouting çağrıları arasında çalışacak şekilde yapılandırılUseEndpoints.

Önceki koda benzer kodları test etme yönergeleri için Test CORS bölümüne bakın.

Yöntem çağrısı, AddCors CORS hizmetlerini uygulamanın hizmet kapsayıcısına ekler:

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();
    }

Daha fazla bilgi için bu belgedeki CORS ilkesi seçeneklerine bakın.

Yöntemler CorsPolicyBuilder , aşağıdaki kodda gösterildiği gibi zincirlenebilir:

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();
}

Not: Belirtilen URL sonunda eğik çizgi () içermemelidir./ URL / ile bitiyorsa, karşılaştırma false döndürür ve hiçbir başlık döndürülmez.

Varsayılan ilke ve ara yazılım ile CORS

Aşağıdaki vurgulanmış kod, varsayılan CORS ilkesini etkinleştirir:

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();
        });
    }
}

Yukarıdaki kod, varsayılan CORS ilkesini tüm denetleyici uç noktalarına uygular.

Uç nokta yönlendirmesi ile Cors'i etkinleştirme

kullanarak RequireCorsCORS'nin uç nokta başına etkinleştirilmesi otomatik denetim öncesi istekleri desteklemez. Daha fazla bilgi için bu GitHub sorununa bakın ve CORS'yi uç nokta yönlendirme ve [HttpOptions] ile test edin.

Uç nokta yönlendirme ile CORS, uzantı yöntemleri kümesi kullanılarak RequireCors uç nokta temelinde etkinleştirilebilir:

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();
        });
    }
}

Önceki kodda:

  • app.UseCors CORS ara yazılımını etkinleştirir. Varsayılan ilke yapılandırılmadığından tek app.UseCors() başına CORS'yi etkinleştirmez.
  • /echo ve denetleyici uç noktaları, belirtilen ilkeyi kullanarak çıkış noktaları arası isteklere izin verir.
  • Varsayılan bir ilke belirtilmediğinden, /echo2 ve Razor Pages uç noktaları kaynaklar arası isteklere izin vermez.

[DisableCors] özniteliği ile uç nokta yönlendirmesi tarafından etkinleştirilen CORS'yi devre dışı bırakmazRequireCors.

Yukarıdakine benzer bir kodu test etme yönergeleri için bkz . Uç nokta yönlendirme ve [HttpOptions] ile CORS'yi test etme.

CorS'yi özniteliklerle etkinleştirme

CORS'yi [EnableCors] özniteliğiyle etkinleştirmek ve yalnızca CORS gerektiren uç noktalara adlandırılmış bir ilke uygulamak en iyi denetimi sağlar.

[EnableCors] özniteliği, CORS'yi genel olarak uygulamaya bir alternatif sağlar. [EnableCors] özniteliği, tüm uç noktalar yerine seçili uç noktalar için CORS'yi etkinleştirir:

  • [EnableCors] varsayılan ilkeyi belirtir.
  • [EnableCors("{Policy String}")] adlandırılmış bir ilke belirtir.

[EnableCors] Özniteliği şu özelliklere uygulanabilir:

  • Razor Sayfa PageModel
  • Controller
  • Denetleyici eylem yöntemi

[EnableCors] özniteliğiyle denetleyicilere, sayfa modellerine veya eylem yöntemlerine farklı ilkeler uygulanabilir. [EnableCors] Öznitelik bir denetleyiciye, sayfa modeline veya eylem yöntemine uygulandığında ve ara yazılımda CORS etkinleştirildiğinde, her iki ilke de uygulanır. İlkeleri birleştirmenizi önermiyoruz. Şunu kullanın [EnableCors] öznitelik veya ara yazılım, aynı uygulamada ikisi birden değil.

Aşağıdaki kod her yönteme farklı bir ilke uygular:

[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(),
        };
    }
}

Aşağıdaki kod iki CORS ilkesi oluşturur:

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();
        });
    }
}

CORS isteklerini sınırlamanın en iyi denetimi için:

  • [EnableCors("MyPolicy")] öğesini adlandırılmış bir ilkeyle kullanın.
  • Varsayılan bir ilke tanımlamayın.
  • Uç nokta yönlendirme kullanmayın.

Sonraki bölümdeki kod önceki listeyi karşılar.

Önceki koda benzer kodları test etme yönergeleri için Test CORS bölümüne bakın.

CORS'yi devre dışı bırakma

[DisableCors] özniteliği, uç nokta yönlendirmesi tarafından etkinleştirilen CORS'yi devre dışı bırakmaz.

Aşağıdaki kod CORS ilkesini "MyPolicy"tanımlar:

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();
        });
    }
}

Aşağıdaki kod, GetValues2 eylemi için CORS’u devre dışı bırakır:

[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();

}

Yukarıdaki kod:

  • Uç nokta yönlendirme ile CORS'yi etkinleştirmez.
  • Varsayılan bir CORS ilkesi tanımlamaz.
  • Denetleyici için CORS ilkesini etkinleştirmek üzere "MyPolicy" kullanır.
  • GetValues2 yöntemi için CORS’u devre dışı bırakır.

Önceki kodu test etmeye ilişkin yönergeler için CORS'u Test Etme bölümüne bakın.

CORS ilke seçenekleri

Bu bölümde, CORS ilkesinde ayarlanabilecek çeşitli seçenekler açıklanmaktadır:

AddPolicy içinde Startup.ConfigureServices çağrılır. Bazı seçenekler için öncelikle CORS'nin çalışma şekli bölümünü okumak yararlı olabilir.

İzin verilen çıkış noktalarını ayarlama

AllowAnyOrigin: Herhangi bir şema (http veya https) ile tüm kaynaklardan GELEN CORS isteklerine izin verir. AllowAnyOrigin güvenli değildir çünkü herhangi bir web sitesi uygulamaya çıkış noktaları arası isteklerde bulunabilir.

Note

AllowAnyOrigin ve AllowCredentials değerlerinin belirtilmesi güvenli olmayan bir yapılandırmadır ve siteler arası istek sahteciliğine neden olabilir. Bir uygulama her iki yöntemle de yapılandırıldığında CORS hizmeti geçersiz bir CORS yanıtı döndürür.

AllowAnyOrigin, ön kontrol isteklerini ve Access-Control-Allow-Origin üst bilgisini etkiler. Daha fazla bilgi için Ön kontrol istekleri adlı bölüme bakın.

SetIsOriginAllowedToAllowWildcardSubdomains: İlkenin IsOriginAllowed özelliğini, kaynağın izin verilip verilmediğini değerlendirirken çıkış noktalarının yapılandırılmış joker karakter etki alanıyla eşleşmesini sağlayan bir işlev olacak şekilde ayarlar.

options.AddPolicy("MyAllowSubdomainPolicy",
    policy =>
    {
        policy.WithOrigins("https://*.example.com")
            .SetIsOriginAllowedToAllowWildcardSubdomains();
    });

Önceki kodda SetIsOriginAllowedToAllowWildcardSubdomains, joker kökeni "https://*.example.com" ile çağrılır. Bu yapılandırma, example.com gibi https://subdomain.example.com veya https://api.example.com alt etki alanlarından gelen CORS isteklerine izin verir. * Joker karakterin alt etki alanı eşleştirmeyi etkinleştirmek için kaynağa eklenmesi gerekir.

İzin verilen HTTP yöntemlerini ayarlama

AllowAnyMethod:

  • Herhangi bir HTTP yöntemine izin verir:
  • Ön kontrol isteklerini ve Access-Control-Allow-Methods üst bilgisini etkiler. Daha fazla bilgi için Ön kontrol istekleri adlı bölüme bakın.

İzin verilen istek üst bilgilerini ayarlayın

Bir CORS isteğinde yazar tanımlı istek üst bilgilerinin gönderilmesine izin vermek için WithHeaders çağrısını yapın ve izin verilen üst bilgileri belirtin:

options.AddPolicy("MyAllowHeadersPolicy",
    policy =>
    {
        // requires using Microsoft.Net.Http.Headers;
        policy.WithOrigins("http://example.com")
               .WithHeaders(HeaderNames.ContentType, "x-custom-header");
    });

Tüm author istek üst bilgilerine izin vermek için AllowAnyHeader çağırın:

options.AddPolicy("MyAllowAllHeadersPolicy",
    policy =>
    {
        policy.WithOrigins("https://*.example.com")
               .AllowAnyHeader();
    });

AllowAnyHeader preflight isteklerini ve Access-Control-Request-Headers üst bilgisini etkiler. Daha fazla bilgi için Ön kontrol istekleri adlı bölüme bakın.

WithHeaders tarafından belirtilen belirli üstbilgilerle eşleşen bir CORS ara yazılım ilkesi, yalnızca Access-Control-Request-Headers içinde gönderilen üstbilgiler WithHeaders içinde belirtilen üstbilgilerle tam olarak eşleştiğinde mümkündür.

Örneğin, aşağıdaki gibi yapılandırılmış bir uygulamayı göz önünde bulundurun:

app.UseCors(policy => policy.WithHeaders(HeaderNames.CacheControl));

CORS ara yazılımı, Content-Language (HeaderNames.ContentLanguage) WithHeaders içinde listelenmediği için aşağıdaki istek üst bilgisine sahip bir ön kontrol isteğini reddeder:

Access-Control-Request-Headers: Cache-Control, Content-Language

Uygulama 200 Tamam yanıtı döndürür ancak CORS üst bilgilerini geri göndermez. Bu nedenle tarayıcı çıkış noktaları arası isteği denemez.

Erişime açılan yanıt başlıklarını ayarlayın

Varsayılan olarak, tarayıcı tüm yanıt üst bilgilerini uygulamaya sunmaz. Daha fazla bilgi için bkz . W3C Çıkış Noktaları Arası Kaynak Paylaşımı (Terminoloji): Basit Yanıt Üst Bilgisi.

Varsayılan olarak kullanılabilen yanıt üst bilgileri şunlardır:

  • Cache-Control
  • Content-Language
  • Content-Type
  • Expires
  • Last-Modified
  • Pragma

CORS belirtimi bu üst bilgileri basit yanıt üst bilgilerini çağırır. Diğer üst bilgileri uygulamanın kullanımına sunmak için WithExposedHeaders çağrısı yapın:

options.AddPolicy("MyExposeResponseHeadersPolicy",
    policy =>
    {
        policy.WithOrigins("https://*.example.com")
               .WithExposedHeaders("x-custom-header");
    });

Kaynaklar arası isteklerde kimlik bilgileri

Kimlik bilgileri, bir CORS isteğinde özel olarak ele alınmalıdır. Varsayılan olarak, tarayıcı çıkış noktaları arası bir istekle kimlik bilgileri göndermez. Kimlik bilgileri, tanımlama bilgilerini ve HTTP kimlik doğrulama şemalarını içerir. Farklı kaynaklar arası bir istekle kimlik bilgilerini göndermek için istemci, XMLHttpRequest.withCredentials değerini true olarak ayarlamalıdır.

XMLHttpRequest doğrudan kullanımı:

var xhr = new XMLHttpRequest();
xhr.open('get', 'https://www.example.com/api/test');
xhr.withCredentials = true;

jQuery kullanma:

$.ajax({
  type: 'get',
  url: 'https://www.example.com/api/test',
  xhrFields: {
    withCredentials: true
  }
});

Fetch API'sini kullanma:

fetch('https://www.example.com/api/test', {
    credentials: 'include'
});

Sunucunun kimlik bilgilerine izin vermesi gerekir. Kaynaklar arası kimlik bilgilerine izin vermek için AllowCredentials çağırın:

options.AddPolicy("MyMyAllowCredentialsPolicy",
    policy =>
    {
        policy.WithOrigins("http://example.com")
               .AllowCredentials();
    });

HTTP yanıtı, sunucunun kaynaklar arası bir istekte kimlik bilgilerine izin verdiğini tarayıcıya bildiren bir Access-Control-Allow-Credentials üst bilgisi içerir.

Tarayıcı kimlik bilgilerini gönderir ancak yanıt geçerli bir Access-Control-Allow-Credentials başlığı içermiyorsa, tarayıcı yanıtı uygulamanın erişimine açmaz ve kaynaklar arası istek başarısız olur.

Kaynaklar arası kimlik bilgilerine izin vermek güvenlik riskidir. Başka bir etki alanındaki bir web sitesi, kullanıcının bilgisi olmadan oturum açmış bir kullanıcının kimlik bilgilerini kullanıcı adına uygulamaya gönderebilir.

CORS belirtimi ayrıca, "*" üstbilgisi mevcutsa kaynakların Access-Control-Allow-Credentials (tüm kaynaklar) olarak ayarlanmasının geçersiz olduğunu belirtir.

Ön kontrol istekleri

Bazı CORS istekleri için tarayıcı, gerçek isteği yapmadan önce ek bir OPTIONS isteği gönderir. Bu istek, ön kontrol isteği olarak adlandırılır. Tarayıcı, aşağıdaki koşulların tümü doğruysa ön kontrol isteğini atlayabilir:

  • İstek yöntemi GET, HEAD veya POST şeklindedir.
  • Uygulama, Accept, Accept-Language, Content-Language, Content-Type veya Last-Event-ID dışında istek üst bilgileri ayarlamaz.
  • Content-Type Üst bilgi ayarlanırsa aşağıdaki değerlerden birine sahiptir:
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain

İstemci isteği için ayarlanan istek üst bilgilerine ilişkin kural, uygulamanın setRequestHeader nesnesi üzerinde XMLHttpRequest çağrısı yaparak ayarladığı üst bilgiler için geçerlidir. CORS spesifikasyonu bu üst bilgileri yazar istek üst bilgileri olarak adlandırır. Kural, tarayıcının ayarlayabileceğiniz , User-Agentveya Hostgibi Content-Lengthüst bilgiler için geçerli değildir.

Aşağıda, bu belgenin Test CORS bölümündeki [Test et] düğmesinden yapılan denetim öncesi isteğine benzer bir örnek yanıt verilmiştir.

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

Ön kontrol isteği, HTTP OPTIONS yöntemini kullanır. Aşağıdaki üst bilgileri içerebilir:

Ön kontrol isteği reddedilirse uygulama 200 OK yanıtı döndürür, ancak CORS başlıklarını ayarlamaz. Bu nedenle tarayıcı çıkış noktaları arası isteği denemez. Reddedilmiş bir preflight isteği örneğini görmek için bu belgedeki CORS’yi Test Et bölümüne bakın.

F12 araçlarını kullanarak, konsol uygulaması tarayıcıya bağlı olarak aşağıdakilerden birine benzer bir hata gösterir:

  • Firefox: Çapraz Kaynak İsteği Engellendi: Aynı Kaynak İlkesi, https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5 konumundaki uzak kaynağın okunmasına izin vermiyor. (Neden: CORS isteği başarılı olmadı). Daha fazla bilgi edinin
  • Chromium tabanlı: 'https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5' kaynağından 'https://cors3.azurewebsites.net' konumuna getirme erişimi CORS ilkesi tarafından engellendi: Ön kontrol isteğine verilen yanıt, erişim denetimi kontrolünden geçmiyor: İstenen kaynakta 'Access-Control-Allow-Origin' üst bilgisi bulunmuyor. Opak yanıt gereksinimlerinize uygunsa, CORS devre dışı bırakılmış olan kaynağı getirmek için isteğin modunu 'cors yok' olarak ayarlayın.

Belirli üstbilgilere izin vermek için WithHeaders çağrısını yapın:

options.AddPolicy("MyAllowHeadersPolicy",
    policy =>
    {
        // requires using Microsoft.Net.Http.Headers;
        policy.WithOrigins("http://example.com")
               .WithHeaders(HeaderNames.ContentType, "x-custom-header");
    });

Tüm author istek üst bilgilerine izin vermek için AllowAnyHeader çağırın:

options.AddPolicy("MyAllowAllHeadersPolicy",
    policy =>
    {
        policy.WithOrigins("https://*.example.com")
               .AllowAnyHeader();
    });

Tarayıcılar, Access-Control-Request-Headers öğesini nasıl ayarladıkları konusunda tutarlı değildir. Aşağıdakilerden biri varsa:

  • Üstbilgiler, "*" dışında herhangi bir değere ayarlanır
  • AllowAnyHeader çağrılır: En az Accept, Content-Typeve Originile birlikte, desteklemek istediğiniz özel üst bilgileri ekleyin.

Otomatik ön kontrol isteği kodu

CORS ilkesi aşağıdakilerden biri uygulandığında:

  • app.UseCors içinde Startup.Configure çağrısı yaparak genel olarak.
  • özniteliğini [EnableCors] kullanma.

ASP.NET Core, denetim öncesi SEÇENEKLER isteğine yanıt verir.

RequireCors kullanılarak CORS'nin uç nokta bazında etkinleştirilmesi şu anda otomatik ön kontrol isteklerini desteklemez.

Bu belgenin Test CORS bölümünde bu davranış gösterilmektedir.

Preflight istekleri için [HttpOptions] özniteliği

CORS uygun ilkeyle etkinleştirildiğinde, ASP.NET Core genellikle CORS denetim öncesi isteklerine otomatik olarak yanıt verir. Bazı senaryolarda bu durum söz konusu olmayabilir. Örneğin, uç nokta yönlendirme ile CORS kullanma.

Aşağıdaki kod, OPTIONS istekleri için uç noktalar oluşturmak için [HttpOptions] özniteliğini kullanır:

[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);
    }

Yukarıdaki kodu test etme yönergeleri için Uç nokta yönlendirmesi ve [HttpOptions] ile CORS'yi test etme bölümüne bkz.

Denetim öncesi süre sonu süresini ayarlama

Access-Control-Max-Age üst bilgisi, preflight isteğine verilen yanıtın ne kadar süreyle önbellekte tutulabileceğini belirtir. Bu üst bilgiyi ayarlamak için SetPreflightMaxAge çağrısını yapın:

options.AddPolicy("MySetPreflightExpirationPolicy",
    policy =>
    {
        policy.WithOrigins("http://example.com")
               .SetPreflightMaxAge(TimeSpan.FromSeconds(2520));
    });

CORS nasıl çalışır?

Bu bölüm, HTTP iletileri düzeyinde bir CORS isteğinde neler olduğunu açıklar.

  • CORS bir güvenlik özelliği değildir . CORS, bir sunucunun aynı kaynak ilkesini gevşetmesini sağlayan bir W3C standardıdır.
  • CORS'ye izin vererek API daha güvenli değildir.
    • CORS'yi zorunlu kılmak istemciye (tarayıcıya) bağlı. Sunucu isteği yürütür ve yanıtı döndürür; hata döndüren ve yanıtı engelleyen istemcidir. Örneğin, aşağıdaki araçlardan herhangi biri sunucu yanıtını görüntüler:
  • Bu, bir sunucunun tarayıcıların normalde yasak olacak farklı bir origin’e yönelik XHR veya Fetch API isteği yürütmesine izin vermesinin bir yoludur.
    • CORS'siz tarayıcılar çıkış noktaları arası istekler yapamaz. CORS'ye başlamadan önce, bu kısıtlamayı aşmak için JSONP kullanıldı. JSONP XHR kullanmaz, yanıtı almak için etiketini kullanır <script> . Betiklerin farklı kaynaklardan yüklenmesine izin verilir.

CORS belirtimi, çıkış noktaları arası istekleri etkinleştiren birkaç yeni HTTP üst bilgisi kullanıma sunulmuştur. Tarayıcı CORS'yi destekliyorsa çıkış noktaları arası istekler için bu üst bilgileri otomatik olarak ayarlar. CORS'yi etkinleştirmek için özel JavaScript kodu gerekmez.

Aşağıda, Değerler test düğmesinden https://cors1.azurewebsites.net/api/values konumuna yapılan farklı kaynaktan gelen bir isteğin örneği verilmiştir. Origin başlığı:

  • İstekte bulunan sitenin etki alanını sağlar.
  • Zorunludur ve ana bilgisayardan farklı olmalıdır.

Genel üst bilgiler

Request URL: https://cors1.azurewebsites.net/api/values
Request Method: GET
Status Code: 200 OK

Yanıt üst bilgileri

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

İstek üst bilgileri

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 ...

OPTIONS isteklerinde sunucu, yanıtta Yanıt üst bilgileriAccess-Control-Allow-Origin: {allowed origin} üst bilgisini ayarlar. Örneğin, dağıtılan örnek, Sil düğmesi OPTIONS isteği aşağıdaki üst bilgileri içerir:

Genel üst bilgiler

Request URL: https://cors3.azurewebsites.net/api/TodoItems2/MyDelete2/5
Request Method: OPTIONS
Status Code: 204 No Content

Yanıt üst bilgileri

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

İstek üst bilgileri

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

Yukarıdaki Yanıt üst bilgilerinde, sunucu yanıttaki Access-Control-Allow-Origin üst bilgisini ayarlar. https://cors1.azurewebsites.net Bu üst bilginin değeri istekten alınan Origin üst bilgiyle eşleşir.

AllowAnyOrigin çağrılırsa, joker karakter değeri olan Access-Control-Allow-Origin: * döndürülür. AllowAnyOrigin herhangi bir çıkış noktası sağlar.

Yanıt Access-Control-Allow-Origin başlığını içermiyorsa, kaynaklar arası istek başarısız olur. Özellikle, tarayıcı isteğe izin vermemektedir. Sunucu başarılı bir yanıt döndürse bile, tarayıcı yanıtı istemci uygulaması için kullanılabilir hale getirmez.

SEÇENEKLER isteklerini görüntüleme

Varsayılan olarak, Chrome ve Edge tarayıcıları F12 araçlarının ağ sekmesinde SEÇENEKLER isteklerini göstermez. SEÇENEKLER isteklerini bu tarayıcılarda görüntülemek için:

  • chrome://flags/#out-of-blink-cors veya edge://flags/#out-of-blink-cors
  • bayrağını devre dışı bırakın.
  • restart.

Firefox, SEÇENEKLER isteklerini varsayılan olarak gösterir.

IIS'de CORS

IIS'ye dağıtım yaparken, sunucu anonim erişime izin verecek şekilde yapılandırılmamışsa CORS'nin Windows Kimlik Doğrulamasından önce çalışması gerekir. Bu senaryoyu desteklemek için IIS CORS modülünün uygulama için yüklenmesi ve yapılandırılması gerekir.

CORS'i test edin

Örnek indirmede CORS'yi test etmek için kod bulunur. İndirmeyi öğrenin. Örnek, Razor Pages eklenmiş bir API projesidir:

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();
        });
    }
}

Warning

WithOrigins("https://localhost:<port>");yalnızca indirme örnek koduna benzer bir örnek uygulamayı test etmek için kullanılmalıdır.

Aşağıdaki ValuesController, test etmek için uç noktaları sunar:

[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, Rick.Docs.Samples.RouteInfo NuGet paketi tarafından sağlanır ve yol bilgilerini görüntüler.

Aşağıdaki yaklaşımlardan birini kullanarak yukarıdaki örnek kodu test edin:

  • Örneği, dotnet run varsayılan URL’sini kullanarak https://localhost:5001 ile çalıştırın.
  • URL’si https://localhost:44398 olan örneği, bağlantı noktası 44398 olarak ayarlanmış şekilde Visual Studio’dan çalıştırın.

F12 araçlarıyla tarayıcı kullanma:

  • Değerler düğmesini seçin ve Ağ sekmesindeki üst bilgileri gözden geçirin.

  • PUT test düğmesini seçin. OPTIONS isteğinin nasıl görüntüleneceğine ilişkin yönergeler için OPTIONS isteklerini görüntüleme bölümüne bakın. PUT testi iki istek oluşturur: OPTIONS ön uçuş isteği ve PUT isteği.

  • GetValues2 [DisableCors] Başarısız bir CORS isteğini tetikleme düğmesini seçin. Belgede belirtildiği gibi yanıt 200 başarı döndürür, ancak CORS isteği yapılmaz. CORS hatasını görmek için Konsol sekmesini seçin. Tarayıcıya bağlı olarak, aşağıdakine benzer bir hata görüntülenir:

    'https://cors1.azurewebsites.net/api/values/GetValues2' origin’inden 'https://cors3.azurewebsites.net' konumundaki kaynağa erişim CORS ilkesi tarafından engellendi: İstenen kaynakta 'Access-Control-Allow-Origin' üst bilgisi bulunmuyor. Opak yanıt gereksinimlerinize uygunsa, CORS devre dışı bırakılmış olan kaynağı getirmek için isteğin modunu 'cors yok' olarak ayarlayın.

CORS özellikli uç noktalar curl veya Fiddler gibi bir araçla test edilebilir. Bir araç kullanılırken, Origin üst bilgisinde belirtilen isteğin kaynağı, isteği alan ana bilgisayardan farklı olmalıdır. İstek, üst bilgisinin değerine göre Origin değilse:

  • CORS ara yazılımının isteği işlemesine gerek yoktur.
  • CORS başlıkları yanıtta döndürülmüyor.

Aşağıdaki komut, bilgi içeren bir OPTIONS isteği göndermek için kullanır curl :

curl -X OPTIONS https://cors3.azurewebsites.net/api/TodoItems2/5 -i

Uç nokta yönlendirme ve [HttpOptions] ile CORS'i test edin

RequireCors kullanılarak uç nokta bazında CORS'un etkinleştirilmesi şu anda otomatik preflight isteklerini desteklemez. CORS'yi etkinleştirmek için uç nokta yönlendirmesini kullanan aşağıdaki kodu göz önünde bulundurun:

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();
        });
    }
}

Aşağıdaki TodoItems1Controller test amaçlı uç noktalar sağlar:

[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);
}

Dağıtıma alınmış https://cors1.azurewebsites.net/test?number=1test sayfasından yukarıdaki kodu test edin.

Delete [EnableCors] ve GET [EnableCors] düğmeleri başarılı olur, çünkü uç noktalarında [EnableCors] bulunur ve preflight isteklerine yanıt verirler. Diğer uç noktalar başarısız olur. JavaScript şunları gönderdiğinden GET düğmesi başarısız oluyor:

 headers: {
      "Content-Type": "x-custom-header"
 },

Aşağıdakiler TodoItems2Controller benzer uç noktalar sağlar, ancak SEÇENEKLER isteklerine yanıt vermek için açık kod içerir:

[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);
}

Yukarıdaki kod, örneği Azure'da dağıtarak test edilebilir. Denetleyici açılır listesinde Preflight'ı ve ardından Denetleyiciyi Ayarla'yı seçin. Uç noktalara yapılan TodoItems2Controller tüm CORS çağrıları başarılı olur.

Ek kaynaklar