Włącz żądania między źródłami (CORS) w ASP.NET CoreEnable Cross-Origin Requests (CORS) in ASP.NET Core

Autorzy Rick Anderson i Kirka LarkinBy Rick Anderson and Kirk Larkin

W tym artykule pokazano, jak włączyć funkcję CORS w aplikacji ASP.NET Core.This article shows how to enable CORS in an ASP.NET Core app.

Zabezpieczenia przeglądarki uniemożliwiają stronom sieci Web wykonywanie żądań do innej domeny niż ta, która była obsługiwana przez stronę sieci Web.Browser security prevents a web page from making requests to a different domain than the one that served the web page. To ograniczenie jest nazywane zasadami tego samego źródła .This restriction is called the same-origin policy . Zasady tego samego źródła uniemożliwiają złośliwej lokacji odczytywanie poufnych danych z innej lokacji.The same-origin policy prevents a malicious site from reading sensitive data from another site. Czasami możesz chcieć zezwolić innym lokacjom na wykonywanie żądań między źródłami do aplikacji.Sometimes, you might want to allow other sites to make cross-origin requests to your app. Aby uzyskać więcej informacji, zobacz artykuł CORS firmy Mozilla.For more information, see the Mozilla CORS article.

Współużytkowanie zasobów między źródłami (CORS):Cross Origin Resource Sharing (CORS):

  • Jest standardem W3C, który umożliwia serwerowi złagodzenie zasad tego samego źródła.Is a W3C standard that allows a server to relax the same-origin policy.
  • Nie jest funkcją zabezpieczeń, funkcja CORS osłabi zabezpieczenia.Is not a security feature, CORS relaxes security. Interfejs API nie jest bezpieczniejszy przez umożliwienie mechanizmu CORS.An API is not safer by allowing CORS. Aby uzyskać więcej informacji, zobacz jak działa mechanizm CORS.For more information, see How CORS works.
  • Zezwala serwerowi jawnie zezwolić na niektóre żądania między źródłami podczas odrzucania innych.Allows a server to explicitly allow some cross-origin requests while rejecting others.
  • Jest bezpieczniejsze i bardziej elastyczne niż wcześniejsze techniki, takie jak JSONP.Is safer and more flexible than earlier techniques, such as JSONP.

Wyświetl lub pobierz przykładowy kod (jak pobrać)View or download sample code (how to download)

To samo źródłoSame origin

Dwa adresy URL mają te same źródła, jeśli mają identyczne schematy, hosty i porty (RFC 6454).Two URLs have the same origin if they have identical schemes, hosts, and ports (RFC 6454).

Te dwa adresy URL mają te same źródła:These two URLs have the same origin:

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

Te adresy URL mają różne źródła niż poprzednie dwa adresy URL:These URLs have different origins than the previous two URLs:

  • https://example.net: Inna domenahttps://example.net: Different domain
  • https://www.example.com/foo.html: Inna poddomenahttps://www.example.com/foo.html: Different subdomain
  • http://example.com/foo.html: Inny schemathttp://example.com/foo.html: Different scheme
  • https://example.com:9000/foo.html: Inny porthttps://example.com:9000/foo.html: Different port

Włączanie mechanizmu CORSEnable CORS

Istnieją trzy sposoby włączania mechanizmu CORS:There are three ways to enable CORS:

Użycie atrybutu [EnableCors] z nazwanymi zasadami zapewnia kontrolkę Finest w ograniczaniu punktów końcowych, które obsługują mechanizm CORS.Using the [EnableCors] attribute with a named policy provides the finest control in limiting endpoints that support CORS.

Ostrzeżenie

UseCors musi być wywoływana przed UseResponseCaching użyciem UseResponseCaching .UseCors must be called before UseResponseCaching when using UseResponseCaching.

Każde podejście jest szczegółowo opisane w poniższych sekcjach.Each approach is detailed in the following sections.

CORS z nazwanymi zasadami i programem pośredniczącymCORS with named policy and middleware

Oprogramowanie pośredniczące CORS obsługuje żądania między źródłami.CORS Middleware handles cross-origin requests. Poniższy kod stosuje zasady CORS do wszystkich punktów końcowych aplikacji z określonymi źródłami:The following code applies a CORS policy to all the app's endpoints with the specified origins:

public class Startup
{
    readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors(options =>
        {
            options.AddPolicy(name: MyAllowSpecificOrigins,
                              builder =>
                              {
                                  builder.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();
        });
    }
}

Powyższy kod ma następujące działanie:The preceding code:

W przypadku routingu punktu końcowego oprogramowanie do obsługi mechanizmu CORS musi być skonfigurowane do wykonywania między wywołaniami UseRouting i UseEndpoints .With endpoint routing, the CORS middleware must be configured to execute between the calls to UseRouting and UseEndpoints.

Zobacz temat CORS testów , aby uzyskać instrukcje dotyczące testowania kodu podobnego do poprzedniego kodu.See Test CORS for instructions on testing code similar to the preceding code.

AddCorsWywołanie metody dodaje usługi CORS do kontenera usługi aplikacji:The AddCors method call adds CORS services to the app's service container:

public class Startup
{
    readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors(options =>
        {
            options.AddPolicy(name: MyAllowSpecificOrigins,
                              builder =>
                              {
                                  builder.WithOrigins("http://example.com",
                                                      "http://www.contoso.com");
                              });
        });

        // services.AddResponseCaching();
        services.AddControllers();
    }

Aby uzyskać więcej informacji, zobacz Opcje zasad CORS w tym dokumencie.For more information, see CORS policy options in this document.

CorsPolicyBuilderMetody mogą być łańcucha, jak pokazano w poniższym kodzie:The CorsPolicyBuilder methods can be chained, as shown in the following code:

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(options =>
    {
        options.AddPolicy(MyAllowSpecificOrigins,
                          builder =>
                          {
                              builder.WithOrigins("http://example.com",
                                                  "http://www.contoso.com")
                                                  .AllowAnyHeader()
                                                  .AllowAnyMethod();
                          });
    });

    services.AddControllers();
}

Uwaga: określony adres URL nie może zawierać końcowego ukośnika ( / ).Note: The specified URL must not contain a trailing slash (/). Jeśli adres URL kończy się na / , porównywanie zwraca false i nie jest zwracany nagłówek.If the URL terminates with /, the comparison returns false and no header is returned.

Mechanizm CORS z domyślnymi zasadami i oprogramowania pośredniczącegoCORS with default policy and middleware

Następujący wyróżniony kod włącza domyślne zasady CORS:The following highlighted code enables the default CORS policy:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors(options =>
        {
            options.AddDefaultPolicy(
                builder =>
                {
                    builder.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();
        });
    }
}

Poprzedni kod stosuje domyślne zasady CORS do wszystkich punktów końcowych kontrolera.The preceding code applies the default CORS policy to all controller endpoints.

Włączanie mechanizmu CORS przy użyciu routingu punktu końcowegoEnable Cors with endpoint routing

Włączenie mechanizmu CORS dla poszczególnych punktów końcowych przy użyciu RequireCors obecnie nie obsługuje automatycznych żądań inspekcji wstępnej.Enabling CORS on a per-endpoint basis using RequireCors currently does not support automatic preflight requests. Aby uzyskać więcej informacji, zobacz ten problem w usłudze GitHub i testowanie mechanizmu CORS przy użyciu routingu punktów końcowych i [HttpOptions].For more information, see this GitHub issue and Test CORS with endpoint routing and [HttpOptions].

Dzięki kierowaniu punktów końcowych można włączyć funkcję CORS dla poszczególnych punktów końcowych przy użyciu RequireCors zestawu metod rozszerzających:With endpoint routing, CORS can be enabled on a per-endpoint basis using the RequireCors set of extension methods:

public class Startup
{
    readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors(options =>
        {
            options.AddPolicy(name: MyAllowSpecificOrigins,
                              builder =>
                              {
                                  builder.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();
        });
    }
}

Powyższy kod ma następujące działanie:In the preceding code:

  • app.UseCors włącza oprogramowanie pośredniczące CORS.app.UseCors enables the CORS middleware. Ponieważ zasady domyślne nie zostały skonfigurowane, app.UseCors() sama nie włącza mechanizmu CORS.Because a default policy hasn't been configured, app.UseCors() alone doesn't enable CORS.
  • /echoPunkty końcowe i umożliwiają Zezwalanie na żądania między źródłami przy użyciu określonych zasad.The /echo and controller endpoints allow cross-origin requests using the specified policy.
  • /echo2 :::no-loc(Razor)::: Punkty końcowe stron i nie zezwalają na żądania między źródłami, ponieważ nie określono żadnych zasad domyślnych.The /echo2 and :::no-loc(Razor)::: Pages endpoints do not allow cross-origin requests because no default policy was specified.

Atrybut [DisableCors] nie wyłącza mechanizmu CORS, który został włączony przez Routing punktów końcowych za pomocą RequireCors .The [DisableCors] attribute does not disable CORS that has been enabled by endpoint routing with RequireCors.

Aby uzyskać instrukcje dotyczące testowania kodu podobnego do powyższego, zobacz artykuł CORS testów z routingiem punktów końcowych i [HttpOptions] .See Test CORS with endpoint routing and [HttpOptions] for instructions on testing code similar to the preceding.

Włączanie mechanizmu CORS z atrybutamiEnable CORS with attributes

Włączanie mechanizmu CORS z atrybutem [EnableCors] i stosowanie nazwanych zasad tylko do tych punktów końcowych, które wymagają mechanizmu CORS, udostępnia formant Finest.Enabling CORS with the [EnableCors] attribute and applying a named policy to only those endpoints that require CORS provides the finest control.

Atrybut [EnableCors] zapewnia alternatywę do stosowania mechanizmu CORS globalnie.The [EnableCors] attribute provides an alternative to applying CORS globally. Ten [EnableCors] atrybut włącza funkcję CORS dla wybranych punktów końcowych, a nie wszystkie punkty końcowe:The [EnableCors] attribute enables CORS for selected endpoints, rather than all endpoints:

  • [EnableCors] Określa zasady domyślne.[EnableCors] specifies the default policy.
  • [EnableCors("{Policy String}")] Określa nazwane zasady.[EnableCors("{Policy String}")] specifies a named policy.

Ten [EnableCors] atrybut może być stosowany do:The [EnableCors] attribute can be applied to:

  • :::no-loc(Razor)::: Stronic PageModel:::no-loc(Razor)::: Page PageModel
  • KontrolerController
  • Metoda akcji kontroleraController action method

Różne zasady można stosować do kontrolerów, modeli stron lub metod akcji z [EnableCors] atrybutem.Different policies can be applied to controllers, page models, or action methods with the [EnableCors] attribute. Gdy [EnableCors] atrybut jest stosowany do kontrolera, modelu strony lub metody akcji, a funkcja CORS jest włączona w oprogramowaniu pośredniczącym, obie zasady są stosowane.When the [EnableCors] attribute is applied to a controller, page model, or action method, and CORS is enabled in middleware, both policies are applied. Zalecamy łączenie zasad. Użyj [EnableCors] atrybutu lub oprogramowania pośredniczącego, a nie obu w tej samej aplikacji.We recommend against combining policies. Use the [EnableCors] attribute or middleware, not both in the same app.

Poniższy kod stosuje różne zasady do każdej metody:The following code applies a different policy to each method:

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

Poniższy kod tworzy dwie zasady CORS:The following code creates two CORS policies:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors(options =>
        {
            options.AddPolicy("Policy1",
                builder =>
                {
                    builder.WithOrigins("http://example.com",
                                        "http://www.contoso.com");
                });

            options.AddPolicy("AnotherPolicy",
                builder =>
                {
                    builder.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();
        });
    }
}

W przypadku kontroli Finest ograniczającej żądania CORS:For the finest control of limiting CORS requests:

  • Używany [EnableCors("MyPolicy")] z nazwanymi zasadami.Use [EnableCors("MyPolicy")] with a named policy.
  • Nie Definiuj zasad domyślnych.Don't define a default policy.
  • Nie używaj routingu punktów końcowych.Don't use endpoint routing.

Kod w następnej sekcji jest zgodny z poprzednią listą.The code in the next section meets the preceding list.

Zobacz temat CORS testów , aby uzyskać instrukcje dotyczące testowania kodu podobnego do poprzedniego kodu.See Test CORS for instructions on testing code similar to the preceding code.

Wyłącz funkcję CORSDisable CORS

Atrybut [DisableCors] nie wyłącza mechanizmu CORS, który został włączony przez Routing punktu końcowego.The [DisableCors] attribute does not disable CORS that has been enabled by endpoint routing.

Poniższy kod definiuje zasady CORS "MyPolicy" :The following code defines the CORS policy "MyPolicy":

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors(options =>
        {
            options.AddPolicy(name: "MyPolicy",
                builder =>
                {
                    builder.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();
        });
    }
}

Poniższy kod wyłącza funkcję CORS dla GetValues2 akcji:The following code disables CORS for the GetValues2 action:

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

}

Powyższy kod ma następujące działanie:The preceding code:

Aby uzyskać instrukcje dotyczące testowania poprzedniego kodu, zobacz temat CORS testów .See Test CORS for instructions on testing the preceding code.

Opcje zasad CORSCORS policy options

W tej sekcji opisano różne opcje, które można ustawić w zasadach CORS:This section describes the various options that can be set in a CORS policy:

AddPolicy jest wywoływana w Startup.ConfigureServices .AddPolicy is called in Startup.ConfigureServices. W przypadku niektórych opcji warto przeczytać najpierw sekcję jak działa mechanizm CORS .For some options, it may be helpful to read the How CORS works section first.

Ustaw dozwolone źródłaSet the allowed origins

AllowAnyOrigin: Umożliwia żądania CORS ze wszystkich źródeł z dowolnym schematem ( http lub https ).AllowAnyOrigin: Allows CORS requests from all origins with any scheme (http or https). AllowAnyOrigin jest niezabezpieczony, ponieważ Każda witryna sieci Web może wprowadzać żądania między źródłami do aplikacji.AllowAnyOrigin is insecure because any website can make cross-origin requests to the app.

Uwaga

Określenie AllowAnyOrigin i AllowCredentials jest niebezpieczną konfiguracją i może skutkować fałszerstwem żądania między lokacjami.Specifying AllowAnyOrigin and AllowCredentials is an insecure configuration and can result in cross-site request forgery. Usługa CORS zwraca nieprawidłową odpowiedź CORS, gdy aplikacja jest skonfigurowana przy użyciu obu metod.The CORS service returns an invalid CORS response when an app is configured with both methods.

AllowAnyOrigin ma wpływ na żądania inspekcji wstępnej i Access-Control-Allow-Origin nagłówek.AllowAnyOrigin affects preflight requests and the Access-Control-Allow-Origin header. Aby uzyskać więcej informacji, zobacz sekcję żądania dotyczące inspekcji wstępnej .For more information, see the Preflight requests section.

SetIsOriginAllowedToAllowWildcardSubdomains: Ustawia IsOriginAllowed Właściwość zasad jako funkcję, która umożliwia pochodzenie w celu dopasowania do skonfigurowanej domeny z symbolami wieloznacznymi podczas oceniania, czy pochodzenie jest dozwolone.SetIsOriginAllowedToAllowWildcardSubdomains: Sets the IsOriginAllowed property of the policy to be a function that allows origins to match a configured wildcard domain when evaluating if the origin is allowed.

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

Ustaw dozwolone metody HTTPSet the allowed HTTP methods

AllowAnyMethod:AllowAnyMethod:

  • Zezwala na dowolną metodę HTTP:Allows any HTTP method:
  • Ma wpływ na żądania inspekcji wstępnej i Access-Control-Allow-Methods nagłówek.Affects preflight requests and the Access-Control-Allow-Methods header. Aby uzyskać więcej informacji, zobacz sekcję żądania dotyczące inspekcji wstępnej .For more information, see the Preflight requests section.

Ustaw nagłówki dozwolonych żądańSet the allowed request headers

Aby zezwolić na wysyłanie określonych nagłówków w żądaniu CORS, nazywanymi nagłówkami żądań autora, wywołaj WithHeaders i określ dozwolone nagłówki:To allow specific headers to be sent in a CORS request, called author request headers, call WithHeaders and specify the allowed headers:

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

Aby zezwolić na wszystkie nagłówki żądań autora, wywołaj AllowAnyHeader :To allow all author request headers, call AllowAnyHeader:

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

AllowAnyHeader ma wpływ na żądania inspekcji wstępnej oraz nagłówek Access-Control-Request-Heads .AllowAnyHeader affects preflight requests and the Access-Control-Request-Headers header. Aby uzyskać więcej informacji, zobacz sekcję żądania dotyczące inspekcji wstępnej .For more information, see the Preflight requests section.

Zasady oprogramowania CORS są zgodne z określonymi nagłówkami określonymi przez WithHeaders jest możliwe tylko wtedy, gdy nagłówki wysyłane Access-Control-Request-Headers dokładnie pasują do nagłówków określonych w WithHeaders .A CORS Middleware policy match to specific headers specified by WithHeaders is only possible when the headers sent in Access-Control-Request-Headers exactly match the headers stated in WithHeaders.

Na przykład rozważ zastosowanie skonfigurowanej aplikacji w następujący sposób:For instance, consider an app configured as follows:

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

Oprogramowanie pośredniczące CORS odrzuca żądanie wstępne z następującym nagłówkiem żądania, ponieważ Content-Language (HeaderNames. ContentLanguage) nie ma na liście WithHeaders :CORS Middleware declines a preflight request with the following request header because Content-Language (HeaderNames.ContentLanguage) isn't listed in WithHeaders:

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

Aplikacja zwraca odpowiedź 200 OK , ale nie wysyła nagłówków CORS z powrotem.The app returns a 200 OK response but doesn't send the CORS headers back. W związku z tym przeglądarka nie próbuje żądania między źródłami.Therefore, the browser doesn't attempt the cross-origin request.

Ustawianie nagłówków uwidocznionych odpowiedziSet the exposed response headers

Domyślnie przeglądarka nie ujawnia wszystkich nagłówków odpowiedzi dla aplikacji.By default, the browser doesn't expose all of the response headers to the app. Aby uzyskać więcej informacji, zobacz temat udostępnianie zasobów między źródłami W3C (terminologia): prosty nagłówek odpowiedzi.For more information, see W3C Cross-Origin Resource Sharing (Terminology): Simple Response Header.

Domyślnie dostępne są nagłówki odpowiedzi:The response headers that are available by default are:

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

Specyfikacja CORS wywołuje te nagłówki proste odpowiedzi .The CORS specification calls these headers simple response headers . Aby udostępnić inne nagłówki aplikacji, wywołaj WithExposedHeaders :To make other headers available to the app, call WithExposedHeaders:

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

Poświadczenia w żądaniach między źródłamiCredentials in cross-origin requests

Poświadczenia wymagają specjalnej obsługi w żądaniu CORS.Credentials require special handling in a CORS request. Domyślnie przeglądarka nie wysyła poświadczeń z żądaniem między źródłami.By default, the browser doesn't send credentials with a cross-origin request. Poświadczenia obejmują :::no-loc(cookie)::: schematy uwierzytelniania s i http.Credentials include :::no-loc(cookie):::s and HTTP authentication schemes. Aby wysłać poświadczenia z żądaniem między źródłami, klient musi mieć ustawioną XMLHttpRequest.withCredentials wartość true .To send credentials with a cross-origin request, the client must set XMLHttpRequest.withCredentials to true.

XMLHttpRequestBezpośrednie używanie:Using XMLHttpRequest directly:

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

Za pomocą jQuery:Using jQuery:

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

Za pomocą interfejsu API pobierania:Using the Fetch API:

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

Serwer musi zezwalać na poświadczenia.The server must allow the credentials. Aby zezwolić na poświadczenia między źródłami, wywołaj AllowCredentials :To allow cross-origin credentials, call AllowCredentials:

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

Odpowiedź HTTP zawiera Access-Control-Allow-Credentials nagłówek, który informuje przeglądarkę, że serwer zezwala na poświadczenia dla żądania między źródłami.The HTTP response includes an Access-Control-Allow-Credentials header, which tells the browser that the server allows credentials for a cross-origin request.

Jeśli przeglądarka wyśle poświadczenia, ale odpowiedź nie zawiera prawidłowego Access-Control-Allow-Credentials nagłówka, przeglądarka nie ujawnia odpowiedzi aplikacji, a żądanie między źródłami nie powiedzie się.If the browser sends credentials but the response doesn't include a valid Access-Control-Allow-Credentials header, the browser doesn't expose the response to the app, and the cross-origin request fails.

Zezwalanie na poświadczenia między źródłami stanowi zagrożenie bezpieczeństwa.Allowing cross-origin credentials is a security risk. Witryna sieci Web w innej domenie może wysyłać poświadczenia zalogowanego użytkownika do aplikacji w imieniu użytkownika bez wiedzy użytkownika.A website at another domain can send a signed-in user's credentials to the app on the user's behalf without the user's knowledge.

Specyfikacja mechanizmu CORS określa również, że ustawienia pochodzenia "*" (wszystkie źródła) są nieprawidłowe, jeśli Access-Control-Allow-Credentials nagłówek jest obecny.The CORS specification also states that setting origins to "*" (all origins) is invalid if the Access-Control-Allow-Credentials header is present.

Żądania wstępnego lotuPreflight requests

W przypadku niektórych żądań CORS przeglądarka wysyła żądanie dodatkowych opcji przed wykonaniem rzeczywistego żądania.For some CORS requests, the browser sends an additional OPTIONS request before making the actual request. To żądanie jest nazywane żądaniem wstępnym.This request is called a preflight request. Przeglądarka może pominąć żądanie inspekcji wstępnej, jeśli spełnione są wszystkie następujące warunki:The browser can skip the preflight request if all the following conditions are true:

  • Metoda żądania ma wartość GET, główna lub OPUBLIKOWANa.The request method is GET, HEAD, or POST.
  • Aplikacja nie ustawia nagłówków żądań innych niż Accept , Accept-Language ,, Content-Language , Content-Type lub Last-Event-ID .The app doesn't set request headers other than Accept, Accept-Language, Content-Language, Content-Type, or Last-Event-ID.
  • Content-TypeNagłówek, jeśli jest ustawiony, ma jedną z następujących wartości:The Content-Type header, if set, has one of the following values:
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain

Reguła dotycząca nagłówków żądań ustawiona dla żądania klienta dotyczy nagłówków, które są ustawiane przez aplikację przez wywołanie setRequestHeader na XMLHttpRequest obiekcie.The rule on request headers set for the client request applies to headers that the app sets by calling setRequestHeader on the XMLHttpRequest object. Specyfikacja CORS wywołuje nagłówki żądania autoratych nagłówków.The CORS specification calls these headers author request headers. Reguła nie ma zastosowania do nagłówków, które można ustawić w przeglądarce, na przykład User-Agent , Host lub Content-Length .The rule doesn't apply to headers the browser can set, such as User-Agent, Host, or Content-Length.

Poniżej znajduje się Przykładowa odpowiedź podobna do żądania inspekcji wstępnej wykonanego z przycisku [Put Test] w sekcji test CORS tego dokumentu.The following is an example response similar to the preflight request made from the [Put test] button in the Test CORS section of this document.

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

Response Headers:
Access-Control-Allow-Methods: PUT,DELETE,GET
Access-Control-Allow-Origin: https://cors1.azurewebsites.net
Server: Microsoft-IIS/10.0
Set-:::no-loc(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

W ramach żądania wstępnego jest stosowana Metoda http Options .The preflight request uses the HTTP OPTIONS method. Może zawierać następujące nagłówki:It may include the following headers:

Jeśli żądanie wstępne nie zostanie odrzucone, aplikacja zwróci 200 OK odpowiedź, ale nie ustawi nagłówków CORS.If the preflight request is denied, the app returns a 200 OK response but doesn't set the CORS headers. W związku z tym przeglądarka nie próbuje żądania między źródłami.Therefore, the browser doesn't attempt the cross-origin request. Przykład odmowy żądania inspekcji wstępnej znajduje się w sekcji test CORS tego dokumentu.For an example of a denied preflight request, see the Test CORS section of this document.

Korzystając z narzędzi F12, aplikacja konsoli pokazuje błąd podobny do jednego z następujących, w zależności od przeglądarki:Using the F12 tools, the console app shows an error similar to one of the following, depending on the browser:

  • Firefox: Zablokowano żądanie między źródłami: te same zasady pochodzenia nie zezwalają na odczytywanie zasobu zdalnego pod adresem https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5 .Firefox: Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5. (Przyczyna: żądanie CORS nie powiodło się).(Reason: CORS request did not succeed). Więcej informacjiLearn More
  • Oparte na chromie: dostęp do pobierania w " https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5 " z pochodzenia " https://cors3.azurewebsites.net " został zablokowany przez zasady CORS: odpowiedź na żądanie wstępnej inspekcji nie przeszedł sprawdzenia kontroli dostępu: brak nagłówka "Access-Control-Allow-Origin" w żądanym zasobie.Chromium based: Access to fetch at 'https://cors1.azurewebsites.net/api/TodoItems1/MyDelete2/5' from origin 'https://cors3.azurewebsites.net' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Jeśli nieprzezroczysta odpowiedź spełnia Twoje wymagania, ustaw tryb żądania na wartość "No-CORS", aby pobrać zasób z wyłączonym mechanizmem CORS.If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

Aby zezwolić na określone nagłówki, wywołaj WithHeaders :To allow specific headers, call WithHeaders:

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

Aby zezwolić na wszystkie nagłówki żądań autora, wywołaj AllowAnyHeader :To allow all author request headers, call AllowAnyHeader:

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

Przeglądarki nie są spójne w sposób ich ustawiania Access-Control-Request-Headers .Browsers aren't consistent in how they set Access-Control-Request-Headers. Jeśli:If either:

  • Nagłówki są ustawione na coś innego niż "*"Headers are set to anything other than "*"
  • AllowAnyHeader jest wywoływana: Uwzględnij co najmniej Accept , Content-Type , i oraz Origin wszystkie niestandardowe nagłówki, które mają być obsługiwane.AllowAnyHeader is called: Include at least Accept, Content-Type, and Origin, plus any custom headers that you want to support.

Kod automatycznego żądania wstępnegoAutomatic preflight request code

Po zastosowaniu zasad CORS:When the CORS policy is applied either:

  • Globalnie przez wywołanie app.UseCors w Startup.Configure .Globally by calling app.UseCors in Startup.Configure.
  • Przy użyciu [EnableCors] atrybutu.Using the [EnableCors] attribute.

ASP.NET Core odpowiada na żądanie opcji inspekcji wstępnej.ASP.NET Core responds to the preflight OPTIONS request.

Włączenie mechanizmu CORS dla poszczególnych punktów końcowych przy użyciu RequireCors obecnie nie obsługuje automatycznych żądań inspekcji wstępnej.Enabling CORS on a per-endpoint basis using RequireCors currently does not support automatic preflight requests.

Sekcja CORS testów tego dokumentu przedstawia takie zachowanie.The Test CORS section of this document demonstrates this behavior.

[HttpOptions] atrybut dla żądań inspekcji wstępnej[HttpOptions] attribute for preflight requests

Gdy mechanizm CORS jest włączony przy użyciu odpowiednich zasad, ASP.NET Core zazwyczaj automatycznie reaguje na żądania funkcji CORS przed inspekcją.When CORS is enabled with the appropriate policy, ASP.NET Core generally responds to CORS preflight requests automatically. W niektórych scenariuszach taka sytuacja może nie być taka sama.In some scenarios, this may not be the case. Na przykład przy użyciu mechanizmu CORS z routingiem punktu końcowego.For example, using CORS with endpoint routing.

Poniższy kod używa atrybutu [HttpOptions] do tworzenia punktów końcowych dla żądań opcji:The following code uses the [HttpOptions] attribute to create endpoints for OPTIONS requests:

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

Aby uzyskać instrukcje dotyczące testowania poprzedniego kodu, zobacz temat CORS testów z routingiem punktów końcowych i [HttpOptions] .See Test CORS with endpoint routing and [HttpOptions] for instructions on testing the preceding code.

Ustaw czas wygaśnięcia inspekcji wstępnejSet the preflight expiration time

Access-Control-Max-AgeNagłówek określa, jak długo odpowiedź na żądanie inspekcji wstępnej może być buforowana.The Access-Control-Max-Age header specifies how long the response to the preflight request can be cached. Aby ustawić ten nagłówek, wywołaj SetPreflightMaxAge :To set this header, call SetPreflightMaxAge:

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

Jak działa mechanizm CORSHow CORS works

W tej sekcji opisano, co się dzieje w żądaniu CORS na poziomie komunikatów http.This section describes what happens in a CORS request at the level of the HTTP messages.

  • Mechanizm CORS nie jest funkcją zabezpieczeń.CORS is not a security feature. CORS jest standardem W3C, który umożliwia serwerowi złagodzenie zasad tego samego źródła.CORS is a W3C standard that allows a server to relax the same-origin policy.
    • Na przykład złośliwy aktor może użyć skryptów między lokacjami (XSS) względem witryny i wykonać żądanie między lokacjami w celu wykraść informacji.For example, a malicious actor could use Cross-Site Scripting (XSS) against your site and execute a cross-site request to their CORS enabled site to steal information.
  • Interfejs API nie jest bezpieczniejszy dzięki umożliwieniu mechanizmu CORS.An API isn't safer by allowing CORS.
    • Aby wymusić mechanizm CORS, należy do klienta (przeglądarki).It's up to the client (browser) to enforce CORS. Serwer wykonuje żądanie i zwraca odpowiedź, jest to klient, który zwraca błąd i blokuje odpowiedź.The server executes the request and returns the response, it's the client that returns an error and blocks the response. Na przykład w dowolnym z poniższych narzędzi zostanie wyświetlona odpowiedź serwera:For example, any of the following tools will display the server response:
  • Jest to sposób, aby serwer zezwalał przeglądarce na wykonywanie żądania interfejsu API XHR lub pobierania między źródłami, które w przeciwnym razie byłoby zabronione.It's a way for a server to allow browsers to execute a cross-origin XHR or Fetch API request that otherwise would be forbidden.
    • Przeglądarki bez funkcji CORS nie mogą wykonywać żądań między źródłami.Browsers without CORS can't do cross-origin requests. Przed zastosowaniem mechanizmu CORS JSONP został użyty do obejścia tego ograniczenia.Before CORS, JSONP was used to circumvent this restriction. JSONP nie używa XHR, używa <script> znacznika do odbierania odpowiedzi.JSONP doesn't use XHR, it uses the <script> tag to receive the response. Skrypty mogą być ładowane między różnymi źródłami.Scripts are allowed to be loaded cross-origin.

Specyfikacja CORS wprowadziła kilka nowych nagłówków HTTP, które umożliwiają żądania między źródłami.The CORS specification introduced several new HTTP headers that enable cross-origin requests. Jeśli przeglądarka obsługuje mechanizm CORS, ustawia te nagłówki automatycznie dla żądań cross-Origin.If a browser supports CORS, it sets these headers automatically for cross-origin requests. Niestandardowy kod JavaScript nie jest wymagany do włączenia mechanizmu CORS.Custom JavaScript code isn't required to enable CORS.

Przycisk Put test na wdrożonym przykładzieThe PUT test button on the deployed sample

Poniżej znajduje się przykład żądania między źródłami z przycisku Testuj wartości do https://cors1.azurewebsites.net/api/values .The following is an example of a cross-origin request from the Values test button to https://cors1.azurewebsites.net/api/values. OriginNagłówek:The Origin header:

  • Zapewnia domenę lokacji, która żąda żądania.Provides the domain of the site that's making the request.
  • Jest wymagany i musi się różnić od hosta.Is required and must be different from the host.

Nagłówki ogólneGeneral headers

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

Nagłówki odpowiedziResponse headers

Content-Encoding: gzip
Content-Type: text/plain; charset=utf-8
Server: Microsoft-IIS/10.0
Set-:::no-loc(Cookie):::: ARRAffinity=8f...;Path=/;HttpOnly;Domain=cors1.azurewebsites.net
Transfer-Encoding: chunked
Vary: Accept-Encoding
X-Powered-By: ASP.NET

Nagłówki żądańRequest headers

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

W obszarze OPTIONS żądania serwer ustawia nagłówek odpowiedzi Access-Control-Allow-Origin: {allowed origin} w odpowiedzi.In OPTIONS requests, the server sets the Response headers Access-Control-Allow-Origin: {allowed origin} header in the response. Przykładowo wdrożone przykładoweżądanie usunięcia [EnableCors] OPTIONS zawiera następujące nagłówki:For example, the deployed sample, Delete [EnableCors] button OPTIONS request contains the following headers:

Nagłówki ogólneGeneral headers

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

Nagłówki odpowiedziResponse headers

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-:::no-loc(Cookie):::: ARRAffinity=8f...;Path=/;HttpOnly;Domain=cors3.azurewebsites.net
Vary: Origin
X-Powered-By: ASP.NET

Nagłówki żądańRequest headers

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

W poprzednich nagłówkach odpowiedzi serwer ustawia nagłówek Access-Control-Allow-Origin w odpowiedzi.In the preceding Response headers , the server sets the Access-Control-Allow-Origin header in the response. https://cors1.azurewebsites.netWartość tego nagłówka pasuje do Origin nagłówka z żądania.The https://cors1.azurewebsites.net value of this header matches the Origin header from the request.

Jeśli AllowAnyOrigin jest wywoływana, Access-Control-Allow-Origin: * jest zwracana wartość symbol wieloznaczny.If AllowAnyOrigin is called, the Access-Control-Allow-Origin: *, the wildcard value, is returned. AllowAnyOrigin zezwala na dowolne źródło.AllowAnyOrigin allows any origin.

Jeśli odpowiedź nie zawiera Access-Control-Allow-Origin nagłówka, żądanie między źródłami nie powiedzie się.If the response doesn't include the Access-Control-Allow-Origin header, the cross-origin request fails. W programie przeglądarka nie zezwala na żądanie.Specifically, the browser disallows the request. Nawet jeśli serwer zwróci pomyślną odpowiedź, przeglądarka nie udostępni odpowiedzi dla aplikacji klienckiej.Even if the server returns a successful response, the browser doesn't make the response available to the client app.

Wyświetl żądania opcjiDisplay OPTIONS requests

Domyślnie przeglądarki Chrome i Edge nie wyświetlają żądań OPTIONS na karcie Sieć narzędzi F12.By default, the Chrome and Edge browsers don't show OPTIONS requests on the network tab of the F12 tools. Aby wyświetlić żądania opcji w następujących przeglądarkach:To display OPTIONS requests in these browsers:

  • chrome://flags/#out-of-blink-cors lub edge://flags/#out-of-blink-corschrome://flags/#out-of-blink-cors or edge://flags/#out-of-blink-cors
  • Wyłącz flagę.disable the flag.
  • uruchomieniu.restart.

W przeglądarce Firefox domyślnie są wyświetlane żądania dotyczące opcji.Firefox shows OPTIONS requests by default.

Mechanizm CORS w usługach IISCORS in IIS

W przypadku wdrażania w programie IIS należy uruchomić funkcję CORS przed uwierzytelnianiem systemu Windows, jeśli serwer nie jest skonfigurowany do zezwalania na dostęp anonimowy.When deploying to IIS, CORS has to run before Windows Authentication if the server isn't configured to allow anonymous access. Aby zapewnić obsługę tego scenariusza, należy zainstalować i skonfigurować moduł CORS usług IIS dla aplikacji.To support this scenario, the IIS CORS module needs to be installed and configured for the app.

Testowanie CORSTest CORS

Pobieranie próbek ma kod do testowania mechanizmu CORS.The sample download has code to test CORS. Zobacz artykuł jak pobrać.See how to download. Przykładem jest projekt interfejsu API ze :::no-loc(Razor)::: stronami dodanymi:The sample is an API project with :::no-loc(Razor)::: Pages added:

public class StartupTest2
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors(options =>
        {
            options.AddPolicy(name: "MyPolicy",
                builder =>
                {
                    builder.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();
        });
    }
}

Ostrzeżenie

WithOrigins("https://localhost:<port>"); powinien być używany tylko do testowania przykładowej aplikacji podobnej do przykładowego kodu pobierania.WithOrigins("https://localhost:<port>"); should only be used for testing a sample app similar to the download sample code.

Poniżej ValuesController podano punkty końcowe do testowania:The following ValuesController provides the endpoints for testing:

[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 jest dostarczany przez pakiet NuGet Rick.Docs. Samples. RouteInfo i wyświetla informacje o trasie.MyDisplayRouteInfo is provided by the Rick.Docs.Samples.RouteInfo NuGet package and displays route information.

Przetestuj poprzedni przykładowy kod przy użyciu jednej z następujących metod:Test the preceding sample code by using one of the following approaches:

  • Użyj wdrożonej przykładowej aplikacji pod adresem https://cors3.azurewebsites.net/ .Use the deployed sample app at https://cors3.azurewebsites.net/. Nie ma potrzeby pobierania przykładu.There is no need to download the sample.
  • Uruchom przykład przy dotnet run użyciu domyślnego adresu URL https://localhost:5001 .Run the sample with dotnet run using the default URL of https://localhost:5001.
  • Uruchom przykład z programu Visual Studio z portem ustawionym na 44398 dla adresu URL https://localhost:44398 .Run the sample from Visual Studio with the port set to 44398 for a URL of https://localhost:44398.

Używanie przeglądarki z narzędziami F12:Using a browser with the F12 tools:

  • Wybierz przycisk wartości i Przejrzyj nagłówki na karcie Sieć .Select the Values button and review the headers in the Network tab.

  • Wybierz przycisk Put test .Select the PUT test button. Zobacz temat Opcje wyświetlania żądania , aby uzyskać instrukcje dotyczące wyświetlania żądania opcji.See Display OPTIONS requests for instructions on displaying the OPTIONS request. Test Put tworzy dwa żądania, żądanie wstępnej kontroli i żądanie Put.The PUT test creates two requests, an OPTIONS preflight request and the PUT request.

  • Wybierz GetValues2 [DisableCors] przycisk, aby wyzwolić nieudane żądanie CORS.Select the GetValues2 [DisableCors] button to trigger a failed CORS request. Jak wspomniano w dokumencie, odpowiedź zwraca 200 sukcesu, ale żądanie CORS nie zostało wykonane.As mentioned in the document, the response returns 200 success, but the CORS request is not made. Wybierz kartę konsola , aby wyświetlić błąd CORS.Select the Console tab to see the CORS error. W zależności od przeglądarki wyświetlane są błędy podobne do następujących:Depending on the browser, an error similar to the following is displayed:

    Dostęp do pobierania z lokalizacji źródłowej został 'https://cors1.azurewebsites.net/api/values/GetValues2' 'https://cors3.azurewebsites.net' zablokowany przez zasady CORS: brak nagłówka "Access-Control-Allow-Origin" w żądanym zasobie.Access to fetch at 'https://cors1.azurewebsites.net/api/values/GetValues2' from origin 'https://cors3.azurewebsites.net' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Jeśli nieprzezroczysta odpowiedź spełnia Twoje wymagania, ustaw tryb żądania na wartość "No-CORS", aby pobrać zasób z wyłączonym mechanizmem CORS.If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

Punkty końcowe z obsługą mechanizmu CORS można testować za pomocą narzędzia, takiego jak zwinięcie, programu Fiddlerlub Poster.CORS-enabled endpoints can be tested with a tool, such as curl, Fiddler, or Postman. W przypadku korzystania z narzędzia, Źródło żądania określone przez Origin nagłówek musi różnić się od hosta przyjmującego żądanie.When using a tool, the origin of the request specified by the Origin header must differ from the host receiving the request. Jeśli żądanie nie jest źródłem krzyżowe na podstawie wartości Origin nagłówka:If the request isn't cross-origin based on the value of the Origin header:

  • Nie ma potrzeby przetwarzania żądania przez oprogramowanie pośredniczące CORS.There's no need for CORS Middleware to process the request.
  • Nagłówki CORS nie są zwracane w odpowiedzi.CORS headers aren't returned in the response.

Następujące polecenie używa polecenia curl , aby wydać żądanie Options z informacjami:The following command uses curl to issue an OPTIONS request with information:

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

Testowanie mechanizmu CORS przy użyciu routingu punktów końcowych i [HttpOptions]Test CORS with endpoint routing and [HttpOptions]

Włączenie mechanizmu CORS dla poszczególnych punktów końcowych przy użyciu RequireCors obecnie nie obsługuje automatycznych żądań inspekcji wstępnej.Enabling CORS on a per-endpoint basis using RequireCors currently does not support automatic preflight requests. Rozważmy następujący kod, który używa routingu punktu końcowego w celu włączenia mechanizmu CORS:Consider the following code which uses endpoint routing to enable CORS:

public class StartupEndPointBugTest
{
    readonly string MyPolicy = "_myPolicy";

    // .WithHeaders(HeaderNames.ContentType, "x-custom-header")
    // forces browsers to require a preflight request with GET

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors(options =>
        {
            options.AddPolicy(name: MyPolicy,
                builder =>
                {
                    builder.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();
        });
    }
}

Poniżej TodoItems1Controller przedstawiono punkty końcowe do testowania:The following TodoItems1Controller provides endpoints for testing:

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

Przetestuj poprzedni kod ze strony testowej wdrożonej próbki.Test the preceding code from the test page of the deployed sample.

Przyciski delete [EnableCors] i Get [EnableCors] zostały wykonane pomyślnie, ponieważ punkty końcowe mają [EnableCors] i odpowiadają na żądania inspekcji wstępnej.The Delete [EnableCors] and GET [EnableCors] buttons succeed, because the endpoints have [EnableCors] and respond to preflight requests. Inne punkty końcowe zakończą się niepowodzeniem.The other endpoints fails. Przycisk Get kończy się niepowodzeniem, ponieważ kod JavaScript wysyła:The GET button fails, because the JavaScript sends:

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

Poniżej TodoItems2Controller znajdują się podobne punkty końcowe, ale zawiera jawny kod odpowiadający na żądania opcji:The following TodoItems2Controller provides similar endpoints, but includes explicit code to respond to OPTIONS requests:

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

Przetestuj poprzedni kod ze strony testowej wdrożonej próbki.Test the preceding code from the test page of the deployed sample. Z listy rozwijanej kontroler wybierz kolejno pozycje Inspekcja wstępna , a następnie Ustaw kontroler .In the Controller drop down list, select Preflight and then Set Controller . Wszystkie wywołania mechanizmu CORS do TodoItems2Controller punktów końcowych powiodły się.All the CORS calls to the TodoItems2Controller endpoints succeed.

Dodatkowe zasobyAdditional resources

Autor: Rick AndersonBy Rick Anderson

W tym artykule pokazano, jak włączyć funkcję CORS w aplikacji ASP.NET Core.This article shows how to enable CORS in an ASP.NET Core app.

Zabezpieczenia przeglądarki uniemożliwiają stronom sieci Web wykonywanie żądań do innej domeny niż ta, która była obsługiwana przez stronę sieci Web.Browser security prevents a web page from making requests to a different domain than the one that served the web page. To ograniczenie jest nazywane zasadami tego samego źródła .This restriction is called the same-origin policy . Zasady tego samego źródła uniemożliwiają złośliwej lokacji odczytywanie poufnych danych z innej lokacji.The same-origin policy prevents a malicious site from reading sensitive data from another site. Czasami możesz chcieć zezwolić innym lokacjom na wykonywanie żądań między źródłami do aplikacji.Sometimes, you might want to allow other sites make cross-origin requests to your app. Aby uzyskać więcej informacji, zobacz artykuł CORS firmy Mozilla.For more information, see the Mozilla CORS article.

Współużytkowanie zasobów między źródłami (CORS):Cross Origin Resource Sharing (CORS):

  • Jest standardem W3C, który umożliwia serwerowi złagodzenie zasad tego samego źródła.Is a W3C standard that allows a server to relax the same-origin policy.
  • Nie jest funkcją zabezpieczeń, funkcja CORS osłabi zabezpieczenia.Is not a security feature, CORS relaxes security. Interfejs API nie jest bezpieczniejszy przez umożliwienie mechanizmu CORS.An API is not safer by allowing CORS. Aby uzyskać więcej informacji, zobacz jak działa mechanizm CORS.For more information, see How CORS works.
  • Zezwala serwerowi jawnie zezwolić na niektóre żądania między źródłami podczas odrzucania innych.Allows a server to explicitly allow some cross-origin requests while rejecting others.
  • Jest bezpieczniejsze i bardziej elastyczne niż wcześniejsze techniki, takie jak JSONP.Is safer and more flexible than earlier techniques, such as JSONP.

Wyświetl lub pobierz przykładowy kod (jak pobrać)View or download sample code (how to download)

To samo źródłoSame origin

Dwa adresy URL mają te same źródła, jeśli mają identyczne schematy, hosty i porty (RFC 6454).Two URLs have the same origin if they have identical schemes, hosts, and ports (RFC 6454).

Te dwa adresy URL mają te same źródła:These two URLs have the same origin:

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

Te adresy URL mają różne źródła niż poprzednie dwa adresy URL:These URLs have different origins than the previous two URLs:

  • https://example.net: Inna domenahttps://example.net: Different domain
  • https://www.example.com/foo.html: Inna poddomenahttps://www.example.com/foo.html: Different subdomain
  • http://example.com/foo.html: Inny schemathttp://example.com/foo.html: Different scheme
  • https://example.com:9000/foo.html: Inny porthttps://example.com:9000/foo.html: Different port

Program Internet Explorer nie traktuje portu podczas porównywania źródeł.Internet Explorer doesn't consider the port when comparing origins.

CORS z nazwanymi zasadami i programem pośredniczącymCORS with named policy and middleware

Oprogramowanie pośredniczące CORS obsługuje żądania między źródłami.CORS Middleware handles cross-origin requests. Poniższy kod włącza mechanizm CORS dla całej aplikacji z określonym źródłem:The following code enables CORS for the entire app with the specified origin:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors(options =>
        {
            options.AddPolicy(MyAllowSpecificOrigins,
            builder =>
            {
                builder.WithOrigins("http://example.com",
                                    "http://www.contoso.com");
            });
        });

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseHsts();
        }

        app.UseCors(MyAllowSpecificOrigins); 

        app.UseHttpsRedirection();
        app.UseMvc();
    }
}

Powyższy kod ma następujące działanie:The preceding code:

AddCorsWywołanie metody dodaje usługi CORS do kontenera usługi aplikacji:The AddCors method call adds CORS services to the app's service container:

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(options =>
    {
        options.AddPolicy(MyAllowSpecificOrigins,
        builder =>
        {
            builder.WithOrigins("http://example.com",
                                "http://www.contoso.com");
        });
    });

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

Aby uzyskać więcej informacji, zobacz Opcje zasad CORS w tym dokumencie.For more information, see CORS policy options in this document .

CorsPolicyBuilderMetoda może łączyć metody łańcucha, jak pokazano w poniższym kodzie:The CorsPolicyBuilder method can chain methods, as shown in the following code:

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(options =>
    {
        options.AddPolicy(MyAllowSpecificOrigins,
        builder =>
        {
            builder.WithOrigins("http://example.com",
                                "http://www.contoso.com")
                                .AllowAnyHeader()
                                .AllowAnyMethod();
        });
    });

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

Uwaga: adres URL nie może zawierać końcowego ukośnika ( / ).Note: The URL must not contain a trailing slash (/). Jeśli adres URL kończy się na / , porównywanie zwraca false i nie jest zwracany nagłówek.If the URL terminates with /, the comparison returns false and no header is returned.

Poniższy kod dotyczy zasad CORS dla wszystkich punktów końcowych aplikacji za pośrednictwem oprogramowania do obsługi mechanizmu CORS:The following code applies CORS policies to all the apps endpoints via CORS Middleware:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseHsts();
    }

    app.UseCors();

    app.UseHttpsRedirection();
    app.UseMvc();
}

Uwaga: UseCors należy wywołać przed UseMvc .Note: UseCors must be called before UseMvc.

Zobacz Włączanie mechanizmu CORS na :::no-loc(Razor)::: stronach, kontrolerach i metodach akcji , aby zastosować zasady CORS na poziomie strony/kontrolera/akcji.See Enable CORS in :::no-loc(Razor)::: Pages, controllers, and action methods to apply CORS policy at the page/controller/action level.

Zobacz temat CORS testów , aby uzyskać instrukcje dotyczące testowania kodu podobnego do poprzedniego kodu.See Test CORS for instructions on testing code similar to the preceding code.

Włączanie mechanizmu CORS z atrybutamiEnable CORS with attributes

Atrybut [ EnableCors ] stanowi alternatywę dla zastosowania mechanizmu CORS globalnie.The [EnableCors] attribute provides an alternative to applying CORS globally. Ten [EnableCors] atrybut włącza funkcję CORS dla wybranych punktów końcowych, a nie wszystkich punktów końcowych.The [EnableCors] attribute enables CORS for selected end points, rather than all end points.

Użyj, [EnableCors] Aby określić zasady domyślne i [EnableCors("{Policy String}")] określić zasady.Use [EnableCors] to specify the default policy and [EnableCors("{Policy String}")] to specify a policy.

Ten [EnableCors] atrybut może być stosowany do:The [EnableCors] attribute can be applied to:

  • :::no-loc(Razor)::: Stronic PageModel:::no-loc(Razor)::: Page PageModel
  • KontrolerController
  • Metoda akcji kontroleraController action method

Możesz zastosować różne zasady do kontrolera/strony-model/akcja z [EnableCors] atrybutem.You can apply different policies to controller/page-model/action with the [EnableCors] attribute. Gdy [EnableCors] atrybut jest stosowany do metody Controller/model/akcja, a funkcja CORS jest włączona w oprogramowaniu pośredniczącym, stosowane są obie zasady.When the [EnableCors] attribute is applied to a controllers/page model/action method, and CORS is enabled in middleware, both policies are applied. Nie zaleca się łączenia zasad.We recommend not combining policies. Użyj [EnableCors] atrybutu lub oprogramowania pośredniczącego, a nie obu .Use the [EnableCors] attribute or middleware, not both . W przypadku korzystania z programu nie [EnableCors] należy definiować zasad domyślnych. notWhen using [EnableCors], do not define a default policy.

Poniższy kod stosuje różne zasady do każdej metody:The following code applies a different policy to each method:

[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]        // Default policy.
    [HttpGet("{id}")]
    public ActionResult<string> Get(int id)
    {
        switch (id)
        {
            case 1:
                return "green widget";
            case 2:
                return "red widget";
            default:
                return NotFound();
        }
    }
}

Poniższy kod tworzy domyślne zasady CORS i zasady o nazwie "AnotherPolicy" :The following code creates a CORS default policy and a policy named "AnotherPolicy":

public class StartupMultiPolicy
{
    public StartupMultiPolicy(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors(options =>
        {
            options.AddDefaultPolicy(
                builder =>
                {
                   
                    builder.WithOrigins("http://example.com",
                                        "http://www.contoso.com");
                });

            options.AddPolicy("AnotherPolicy",
                builder =>
                {
                    builder.WithOrigins("http://www.contoso.com")
                                        .AllowAnyHeader()
                                        .AllowAnyMethod();
                });

        });

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseMvc();
    }
}

Wyłącz funkcję CORSDisable CORS

Atrybut [ DisableCors ] wyłącza funkcję CORS dla kontrolera/strony-modelu/akcji.The [DisableCors] attribute disables CORS for the controller/page-model/action.

Opcje zasad CORSCORS policy options

W tej sekcji opisano różne opcje, które można ustawić w zasadach CORS:This section describes the various options that can be set in a CORS policy:

AddPolicy jest wywoływana w Startup.ConfigureServices .AddPolicy is called in Startup.ConfigureServices. W przypadku niektórych opcji warto przeczytać najpierw sekcję jak działa mechanizm CORS .For some options, it may be helpful to read the How CORS works section first.

Ustaw dozwolone źródłaSet the allowed origins

AllowAnyOrigin: Umożliwia żądania CORS ze wszystkich źródeł z dowolnym schematem ( http lub https ).AllowAnyOrigin: Allows CORS requests from all origins with any scheme (http or https). AllowAnyOrigin jest niezabezpieczony, ponieważ Każda witryna sieci Web może wprowadzać żądania między źródłami do aplikacji.AllowAnyOrigin is insecure because any website can make cross-origin requests to the app.

Uwaga

Określenie AllowAnyOrigin i AllowCredentials jest niebezpieczną konfiguracją i może skutkować fałszerstwem żądania między lokacjami.Specifying AllowAnyOrigin and AllowCredentials is an insecure configuration and can result in cross-site request forgery. W przypadku bezpiecznej aplikacji należy określić dokładną listę źródeł, jeśli klient musi autoryzować sam do uzyskiwania dostępu do zasobów serwera.For a secure app, specify an exact list of origins if the client must authorize itself to access server resources.

AllowAnyOrigin ma wpływ na żądania inspekcji wstępnej i Access-Control-Allow-Origin nagłówek.AllowAnyOrigin affects preflight requests and the Access-Control-Allow-Origin header. Aby uzyskać więcej informacji, zobacz sekcję żądania dotyczące inspekcji wstępnej .For more information, see the Preflight requests section.

SetIsOriginAllowedToAllowWildcardSubdomains: Ustawia IsOriginAllowed Właściwość zasad jako funkcję, która umożliwia pochodzenie w celu dopasowania do skonfigurowanej domeny z symbolami wieloznacznymi podczas oceniania, czy pochodzenie jest dozwolone.SetIsOriginAllowedToAllowWildcardSubdomains: Sets the IsOriginAllowed property of the policy to be a function that allows origins to match a configured wildcard domain when evaluating if the origin is allowed.

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

Ustaw dozwolone metody HTTPSet the allowed HTTP methods

AllowAnyMethod:AllowAnyMethod:

  • Zezwala na dowolną metodę HTTP:Allows any HTTP method:
  • Ma wpływ na żądania inspekcji wstępnej i Access-Control-Allow-Methods nagłówek.Affects preflight requests and the Access-Control-Allow-Methods header. Aby uzyskać więcej informacji, zobacz sekcję żądania dotyczące inspekcji wstępnej .For more information, see the Preflight requests section.

Ustaw nagłówki dozwolonych żądańSet the allowed request headers

Aby zezwolić na wysyłanie określonych nagłówków w żądaniu CORS, nazywanymi nagłówkami żądań autora , wywołaj WithHeaders i określ dozwolone nagłówki:To allow specific headers to be sent in a CORS request, called author request headers , call WithHeaders and specify the allowed headers:

options.AddPolicy("AllowHeaders",
    builder =>
    {
        builder.WithOrigins("http://example.com")
               .WithHeaders(HeaderNames.ContentType, "x-custom-header");
    });

Aby zezwolić na wszystkie nagłówki żądań autora, wywołaj AllowAnyHeader :To allow all author request headers, call AllowAnyHeader:

options.AddPolicy("AllowAllHeaders",
    builder =>
    {
        builder.WithOrigins("http://example.com")
               .AllowAnyHeader();
    });

To ustawienie ma wpływ na żądania inspekcji wstępnej i Access-Control-Request-Headers nagłówek.This setting affects preflight requests and the Access-Control-Request-Headers header. Aby uzyskać więcej informacji, zobacz sekcję żądania dotyczące inspekcji wstępnej .For more information, see the Preflight requests section.

Oprogramowanie pośredniczące CORS zawsze umożliwia wysyłanie czterech nagłówków w Access-Control-Request-Headers celu, niezależnie od wartości skonfigurowanych w CorsPolicy. Heads.CORS Middleware always allows four headers in the Access-Control-Request-Headers to be sent regardless of the values configured in CorsPolicy.Headers. Ta lista nagłówków obejmuje:This list of headers includes:

  • Accept
  • Accept-Language
  • Content-Language
  • Origin

Na przykład rozważ zastosowanie skonfigurowanej aplikacji w następujący sposób:For instance, consider an app configured as follows:

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

Oprogramowanie pośredniczące CORS pomyślnie reaguje na żądanie inspekcji wstępnej z następującym nagłówkiem żądania, ponieważ Content-Language jest zawsze dozwolone:CORS Middleware responds successfully to a preflight request with the following request header because Content-Language is always permitted:

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

Ustawianie nagłówków uwidocznionych odpowiedziSet the exposed response headers

Domyślnie przeglądarka nie ujawnia wszystkich nagłówków odpowiedzi dla aplikacji.By default, the browser doesn't expose all of the response headers to the app. Aby uzyskać więcej informacji, zobacz temat udostępnianie zasobów między źródłami W3C (terminologia): prosty nagłówek odpowiedzi.For more information, see W3C Cross-Origin Resource Sharing (Terminology): Simple Response Header.

Domyślnie dostępne są nagłówki odpowiedzi:The response headers that are available by default are:

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

Specyfikacja CORS wywołuje te nagłówki proste odpowiedzi .The CORS specification calls these headers simple response headers . Aby udostępnić inne nagłówki aplikacji, wywołaj WithExposedHeaders :To make other headers available to the app, call WithExposedHeaders:

options.AddPolicy("ExposeResponseHeaders",
    builder =>
    {
        builder.WithOrigins("http://example.com")
               .WithExposedHeaders("x-custom-header");
    });

Poświadczenia w żądaniach między źródłamiCredentials in cross-origin requests

Poświadczenia wymagają specjalnej obsługi w żądaniu CORS.Credentials require special handling in a CORS request. Domyślnie przeglądarka nie wysyła poświadczeń z żądaniem między źródłami.By default, the browser doesn't send credentials with a cross-origin request. Poświadczenia obejmują :::no-loc(cookie)::: schematy uwierzytelniania s i http.Credentials include :::no-loc(cookie):::s and HTTP authentication schemes. Aby wysłać poświadczenia z żądaniem między źródłami, klient musi mieć ustawioną XMLHttpRequest.withCredentials wartość true .To send credentials with a cross-origin request, the client must set XMLHttpRequest.withCredentials to true.

XMLHttpRequestBezpośrednie używanie:Using XMLHttpRequest directly:

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

Za pomocą jQuery:Using jQuery:

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

Za pomocą interfejsu API pobierania:Using the Fetch API:

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

Serwer musi zezwalać na poświadczenia.The server must allow the credentials. Aby zezwolić na poświadczenia między źródłami, wywołaj AllowCredentials :To allow cross-origin credentials, call AllowCredentials:

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

Odpowiedź HTTP zawiera Access-Control-Allow-Credentials nagłówek, który informuje przeglądarkę, że serwer zezwala na poświadczenia dla żądania między źródłami.The HTTP response includes an Access-Control-Allow-Credentials header, which tells the browser that the server allows credentials for a cross-origin request.

Jeśli przeglądarka wyśle poświadczenia, ale odpowiedź nie zawiera prawidłowego Access-Control-Allow-Credentials nagłówka, przeglądarka nie ujawnia odpowiedzi aplikacji, a żądanie między źródłami nie powiedzie się.If the browser sends credentials but the response doesn't include a valid Access-Control-Allow-Credentials header, the browser doesn't expose the response to the app, and the cross-origin request fails.

Zezwalanie na poświadczenia między źródłami stanowi zagrożenie bezpieczeństwa.Allowing cross-origin credentials is a security risk. Witryna sieci Web w innej domenie może wysyłać poświadczenia zalogowanego użytkownika do aplikacji w imieniu użytkownika bez wiedzy użytkownika.A website at another domain can send a signed-in user's credentials to the app on the user's behalf without the user's knowledge.

Specyfikacja mechanizmu CORS określa również, że ustawienia pochodzenia "*" (wszystkie źródła) są nieprawidłowe, jeśli Access-Control-Allow-Credentials nagłówek jest obecny.The CORS specification also states that setting origins to "*" (all origins) is invalid if the Access-Control-Allow-Credentials header is present.

Żądania wstępnego lotuPreflight requests

W przypadku niektórych żądań CORS przeglądarka wysyła dodatkowe żądanie przed wykonaniem rzeczywistego żądania.For some CORS requests, the browser sends an additional request before making the actual request. To żądanie jest nazywane żądaniem wstępnym .This request is called a preflight request . Jeśli spełnione są następujące warunki, przeglądarka może pominąć żądanie wstępne:The browser can skip the preflight request if the following conditions are true:

  • Metoda żądania ma wartość GET, główna lub OPUBLIKOWANa.The request method is GET, HEAD, or POST.
  • Aplikacja nie ustawia nagłówków żądań innych niż Accept , Accept-Language ,, Content-Language , Content-Type lub Last-Event-ID .The app doesn't set request headers other than Accept, Accept-Language, Content-Language, Content-Type, or Last-Event-ID.
  • Content-TypeNagłówek, jeśli jest ustawiony, ma jedną z następujących wartości:The Content-Type header, if set, has one of the following values:
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain

Reguła dotycząca nagłówków żądań ustawiona dla żądania klienta dotyczy nagłówków, które są ustawiane przez aplikację przez wywołanie setRequestHeader na XMLHttpRequest obiekcie.The rule on request headers set for the client request applies to headers that the app sets by calling setRequestHeader on the XMLHttpRequest object. Specyfikacja CORS wywołuje nagłówki żądania autora tych nagłówków.The CORS specification calls these headers author request headers . Reguła nie ma zastosowania do nagłówków, które można ustawić w przeglądarce, na przykład User-Agent , Host lub Content-Length .The rule doesn't apply to headers the browser can set, such as User-Agent, Host, or Content-Length.

Poniżej znajduje się przykład żądania wstępnego:The following is an example of a preflight request:

OPTIONS https://myservice.azurewebsites.net/api/test HTTP/1.1
Accept: */*
Origin: https://myclient.azurewebsites.net
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: accept, x-my-custom-header
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)
Host: myservice.azurewebsites.net
Content-Length: 0

Żądanie przed inspekcją używa metody HTTP OPTIONS.The pre-flight request uses the HTTP OPTIONS method. Zawiera dwa specjalne nagłówki:It includes two special headers:

  • Access-Control-Request-Method: Metoda HTTP, która będzie używana dla rzeczywistego żądania.Access-Control-Request-Method: The HTTP method that will be used for the actual request.
  • Access-Control-Request-Headers: Lista nagłówków żądań, które aplikacja ustawia na rzeczywiste żądanie.Access-Control-Request-Headers: A list of request headers that the app sets on the actual request. Jak wspomniano wcześniej, nie obejmuje to nagłówków, które są ustawiane przez przeglądarkę, takich jak User-Agent .As stated earlier, this doesn't include headers that the browser sets, such as User-Agent.

Gdy mechanizm CORS jest włączony przy użyciu odpowiednich zasad, ASP.NET Core zwykle automatycznie reaguje na żądania inspekcji wstępnej.When CORS is enabled with the appropriate policy, ASP.NET Core generally automatically responds to CORS preflight requests. Zobacz [HttpOptions] atrybutu dla żądań inspekcji wstępnej.See [HttpOptions] attribute for preflight requests.

Żądanie inspekcji wstępnej CORS może zawierać Access-Control-Request-Headers nagłówek, który wskazuje serwerowi nagłówki wysyłane z rzeczywistym żądaniem.A CORS preflight request might include an Access-Control-Request-Headers header, which indicates to the server the headers that are sent with the actual request.

Aby zezwolić na określone nagłówki, wywołaj WithHeaders :To allow specific headers, call WithHeaders:

options.AddPolicy("AllowHeaders",
    builder =>
    {
        builder.WithOrigins("http://example.com")
               .WithHeaders(HeaderNames.ContentType, "x-custom-header");
    });

Aby zezwolić na wszystkie nagłówki żądań autora, wywołaj AllowAnyHeader :To allow all author request headers, call AllowAnyHeader:

options.AddPolicy("AllowAllHeaders",
    builder =>
    {
        builder.WithOrigins("http://example.com")
               .AllowAnyHeader();
    });

Przeglądarki nie są w pełni spójne w sposób ich ustawiania Access-Control-Request-Headers .Browsers aren't entirely consistent in how they set Access-Control-Request-Headers. Jeśli ustawisz nagłówki jako elementy inne niż "*" (lub użycie AllowAnyHeader ), należy uwzględnić co najmniej Accept , Content-Type i i Origin wszystkie niestandardowe nagłówki, które mają być obsługiwane.If you set headers to anything other than "*" (or use AllowAnyHeader), you should include at least Accept, Content-Type, and Origin, plus any custom headers that you want to support.

Poniżej znajduje się Przykładowa odpowiedź na żądanie inspekcji wstępnej (przy założeniu, że serwer zezwala na żądanie):The following is an example response to the preflight request (assuming that the server allows the request):

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 0
Access-Control-Allow-Origin: https://myclient.azurewebsites.net
Access-Control-Allow-Headers: x-my-custom-header
Access-Control-Allow-Methods: PUT
Date: Wed, 20 May 2015 06:33:22 GMT

Odpowiedź zawiera nagłówek, Access-Control-Allow-Methods który zawiera listę dozwolonych metod i opcjonalnie Access-Control-Allow-Headers nagłówek, który zawiera listę dozwolonych nagłówków.The response includes an Access-Control-Allow-Methods header that lists the allowed methods and optionally an Access-Control-Allow-Headers header, which lists the allowed headers. W przypadku pomyślnego przeprowadzenia żądania wstępnego przeglądarka wyśle rzeczywiste żądanie.If the preflight request succeeds, the browser sends the actual request.

Jeśli żądanie wstępne nie zostanie odrzucone, aplikacja zwróci odpowiedź 200 OK , ale nie wyśle nagłówków CORS z powrotem.If the preflight request is denied, the app returns a 200 OK response but doesn't send the CORS headers back. W związku z tym przeglądarka nie próbuje żądania między źródłami.Therefore, the browser doesn't attempt the cross-origin request.

Ustaw czas wygaśnięcia inspekcji wstępnejSet the preflight expiration time

Access-Control-Max-AgeNagłówek określa, jak długo odpowiedź na żądanie inspekcji wstępnej może być buforowana.The Access-Control-Max-Age header specifies how long the response to the preflight request can be cached. Aby ustawić ten nagłówek, wywołaj SetPreflightMaxAge :To set this header, call SetPreflightMaxAge:

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

Jak działa mechanizm CORSHow CORS works

W tej sekcji opisano, co się dzieje w żądaniu CORS na poziomie komunikatów http.This section describes what happens in a CORS request at the level of the HTTP messages.

  • Mechanizm CORS nie jest funkcją zabezpieczeń.CORS is not a security feature. CORS jest standardem W3C, który umożliwia serwerowi złagodzenie zasad tego samego źródła.CORS is a W3C standard that allows a server to relax the same-origin policy.
  • Interfejs API nie jest bezpieczniejszy przez umożliwienie mechanizmu CORS.Your API is not safer by allowing CORS.
    • Aby wymusić mechanizm CORS, należy do klienta (przeglądarki).It's up to the client (browser) to enforce CORS. Serwer wykonuje żądanie i zwraca odpowiedź, jest to klient, który zwraca błąd i blokuje odpowiedź.The server executes the request and returns the response, it's the client that returns an error and blocks the response. Na przykład w dowolnym z poniższych narzędzi zostanie wyświetlona odpowiedź serwera:For example, any of the following tools will display the server response:
  • Jest to sposób, aby serwer zezwalał przeglądarce na wykonywanie żądania interfejsu API XHR lub pobierania między źródłami, które w przeciwnym razie byłoby zabronione.It's a way for a server to allow browsers to execute a cross-origin XHR or Fetch API request that otherwise would be forbidden.
    • Przeglądarki (bez CORS) nie mogą wykonywać żądań między źródłami.Browsers (without CORS) can't do cross-origin requests. Przed zastosowaniem mechanizmu CORS JSONP został użyty do obejścia tego ograniczenia.Before CORS, JSONP was used to circumvent this restriction. JSONP nie używa XHR, używa <script> znacznika do odbierania odpowiedzi.JSONP doesn't use XHR, it uses the <script> tag to receive the response. Skrypty mogą być ładowane między różnymi źródłami.Scripts are allowed to be loaded cross-origin.

Specyfikacja CORS wprowadziła kilka nowych nagłówków HTTP, które umożliwiają żądania między źródłami.The CORS specification introduced several new HTTP headers that enable cross-origin requests. Jeśli przeglądarka obsługuje mechanizm CORS, ustawia te nagłówki automatycznie dla żądań cross-Origin.If a browser supports CORS, it sets these headers automatically for cross-origin requests. Niestandardowy kod JavaScript nie jest wymagany do włączenia mechanizmu CORS.Custom JavaScript code isn't required to enable CORS.

Poniżej przedstawiono przykład żądania między źródłami danych.The following is an example of a cross-origin request. OriginNagłówek zawiera domenę lokacji, która żąda żądania.The Origin header provides the domain of the site that's making the request. OriginNagłówek jest wymagany i musi się różnić od hosta.The Origin header is required and must be different from the host.

GET https://myservice.azurewebsites.net/api/test HTTP/1.1
Referer: https://myclient.azurewebsites.net/
Accept: */*
Accept-Language: en-US
Origin: https://myclient.azurewebsites.net
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)
Host: myservice.azurewebsites.net

Jeśli serwer zezwala na żądanie, ustawia Access-Control-Allow-Origin nagłówek w odpowiedzi.If the server allows the request, it sets the Access-Control-Allow-Origin header in the response. Wartość tego nagłówka jest zgodna z Origin nagłówkiem z żądania lub jest wartością symbolu wieloznacznego "*" , co oznacza, że wszystkie źródła są dozwolone:The value of this header either matches the Origin header from the request or is the wildcard value "*", meaning that any origin is allowed:

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: text/plain; charset=utf-8
Access-Control-Allow-Origin: https://myclient.azurewebsites.net
Date: Wed, 20 May 2015 06:27:30 GMT
Content-Length: 12

Test message

Jeśli odpowiedź nie zawiera Access-Control-Allow-Origin nagłówka, żądanie między źródłami nie powiedzie się.If the response doesn't include the Access-Control-Allow-Origin header, the cross-origin request fails. W programie przeglądarka nie zezwala na żądanie.Specifically, the browser disallows the request. Nawet jeśli serwer zwróci pomyślną odpowiedź, przeglądarka nie udostępni odpowiedzi dla aplikacji klienckiej.Even if the server returns a successful response, the browser doesn't make the response available to the client app.

Testowanie CORSTest CORS

Aby przetestować CORS:To test CORS:

  1. Utwórz projekt interfejsu API.Create an API project. Możesz również pobrać przykład.Alternatively, you can download the sample.
  2. Włącz funkcję CORS przy użyciu jednego z metod w tym dokumencie.Enable CORS using one of the approaches in this document. Przykład:For example:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseHsts();
    }

    // Shows UseCors with CorsPolicyBuilder.
    app.UseCors(builder =>
    {
        builder.WithOrigins("http://example.com",
                            "http://www.contoso.com",
                            "https://localhost:44375",
                            "https://localhost:5001");
    });

    app.UseHttpsRedirection();
    app.UseMvc();
}

Ostrzeżenie

WithOrigins("https://localhost:<port>"); powinien być używany tylko do testowania przykładowej aplikacji podobnej do przykładowego kodu pobierania.WithOrigins("https://localhost:<port>"); should only be used for testing a sample app similar to the download sample code.

  1. Utwórz projekt aplikacji sieci Web ( :::no-loc(Razor)::: strony lub MVC).Create a web app project (:::no-loc(Razor)::: Pages or MVC). Przykład używa :::no-loc(Razor)::: stron.The sample uses :::no-loc(Razor)::: Pages. Aplikację sieci Web można utworzyć w tym samym rozwiązaniu co projekt interfejsu API.You can create the web app in the same solution as the API project.
  2. Dodaj następujący wyróżniony kod do pliku index. cshtml :Add the following highlighted code to the Index.cshtml file:
@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

<div class="text-center">
    <h1 class="display-4">CORS Test</h1>
</div>

<div>
    <input type="button" value="Test" 
           onclick="requestVal('https://<web app>.azurewebsites.net/api/values')" />
    <span id='result'></span>
</div>

<script>
    function requestVal(uri) {
        const resultSpan = document.getElementById('result');

        fetch(uri)
            .then(response => response.json())
            .then(data => resultSpan.innerText = data)
            .catch(error => resultSpan.innerText = 'See F12 Console for error');
    }
</script>
  1. W poprzednim kodzie Zastąp ciąg url: 'https://<web app>.azurewebsites.net/api/values/1', adresem URL wdrożonej aplikacji.In the preceding code, replace url: 'https://<web app>.azurewebsites.net/api/values/1', with the URL to the deployed app.

  2. Wdróż projekt interfejsu API.Deploy the API project. Na przykład Wdróż na platformie Azure.For example, deploy to Azure.

  3. Uruchom :::no-loc(Razor)::: strony lub aplikację MVC na pulpicie, a następnie kliknij przycisk Testuj .Run the :::no-loc(Razor)::: Pages or MVC app from the desktop and click on the Test button. Użyj narzędzi F12, aby przejrzeć komunikaty o błędach.Use the F12 tools to review error messages.

  4. Usuń pochodzenie hosta lokalnego z WithOrigins i Wdróż aplikację.Remove the localhost origin from WithOrigins and deploy the app. Alternatywnie Uruchom aplikację kliencką z innym portem.Alternatively, run the client app with a different port. Na przykład uruchom polecenie z programu Visual Studio.For example, run from Visual Studio.

  5. Przetestuj za pomocą aplikacji klienckiej.Test with the client app. Błędy funkcji CORS zwracają błąd, ale komunikat o błędzie nie jest dostępny dla języka JavaScript.CORS failures return an error, but the error message isn't available to JavaScript. Aby wyświetlić błąd, Użyj karty konsola w narzędziach F12.Use the console tab in the F12 tools to see the error. W zależności od przeglądarki pojawia się błąd (w konsoli narzędzia F12) podobny do poniższego:Depending on the browser, you get an error (in the F12 tools console) similar to the following:

    • Korzystanie z przeglądarki Microsoft Edge:Using Microsoft Edge:

      SEC7120: [CORS] https://localhost:44375 nie znaleziono źródła https://localhost:44375 w nagłówku odpowiedzi "Access-Control-Allow-Origin" dla zasobu Cross-Origin w https://webapi.azurewebsites.net/api/values/1SEC7120: [CORS] The origin https://localhost:44375 did not find https://localhost:44375 in the Access-Control-Allow-Origin response header for cross-origin resource at https://webapi.azurewebsites.net/api/values/1

    • Korzystanie z programu Chrome:Using Chrome:

      Dostęp do elementu XMLHttpRequest w lokalizacji https://webapi.azurewebsites.net/api/values/1 z punktu początkowego został https://localhost:44375 zablokowany przez zasady CORS: brak nagłówka "Access-Control-Allow-Origin" w żądanym zasobie.Access to XMLHttpRequest at https://webapi.azurewebsites.net/api/values/1 from origin https://localhost:44375 has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Punkty końcowe z obsługą mechanizmu CORS można testować za pomocą narzędzia, takiego jak programu Fiddler lub Poster.CORS-enabled endpoints can be tested with a tool, such as Fiddler or Postman. W przypadku korzystania z narzędzia, Źródło żądania określone przez Origin nagłówek musi różnić się od hosta przyjmującego żądanie.When using a tool, the origin of the request specified by the Origin header must differ from the host receiving the request. Jeśli żądanie nie jest źródłem krzyżowe na podstawie wartości Origin nagłówka:If the request isn't cross-origin based on the value of the Origin header:

  • Nie ma potrzeby przetwarzania żądania przez oprogramowanie pośredniczące CORS.There's no need for CORS Middleware to process the request.
  • Nagłówki CORS nie są zwracane w odpowiedzi.CORS headers aren't returned in the response.

Mechanizm CORS w usługach IISCORS in IIS

W przypadku wdrażania w programie IIS należy uruchomić funkcję CORS przed uwierzytelnianiem systemu Windows, jeśli serwer nie jest skonfigurowany do zezwalania na dostęp anonimowy.When deploying to IIS, CORS has to run before Windows Authentication if the server isn't configured to allow anonymous access. Aby zapewnić obsługę tego scenariusza, należy zainstalować i skonfigurować moduł CORS usług IIS dla aplikacji.To support this scenario, the IIS CORS module needs to be installed and configured for the app.

Dodatkowe zasobyAdditional resources