Abilitare le richieste tra le origini (CORS) in ASP.NET CoreEnable Cross-Origin Requests (CORS) in ASP.NET Core

Di Rick AndersonBy Rick Anderson

Questo articolo illustra come abilitare CORS in un'app ASP.NET Core.This article shows how to enable CORS in an ASP.NET Core app.

La sicurezza del browser impedisce a una pagina Web di eseguire richieste a un dominio diverso da quello che ha gestito la pagina Web.Browser security prevents a web page from making requests to a different domain than the one that served the web page. Questa restrizione è detta criterio della stessa origine.This restriction is called the same-origin policy. Il criterio della stessa origine impedisce a un sito dannoso di leggere dati sensibili da un altro sito.The same-origin policy prevents a malicious site from reading sensitive data from another site. In alcuni casi potrebbe essere necessario consentire ad altri siti di effettuare richieste tra le origini all'app.Sometimes, you might want to allow other sites make cross-origin requests to your app. Per altre informazioni, vedere l' articolo relativo a Mozilla CORS.For more information, see the Mozilla CORS article.

Condivisione risorse tra le origini (CORS):Cross Origin Resource Sharing (CORS):

  • È uno standard W3C che consente a un server di ridurre i criteri della stessa origine.Is a W3C standard that allows a server to relax the same-origin policy.
  • Non è una funzionalità di sicurezza, CORS rilassa la sicurezza.Is not a security feature, CORS relaxes security. Un'API non è più sicura consentendo CORS.An API is not safer by allowing CORS. Per ulteriori informazioni, vedere funzionamento di CORS.For more information, see How CORS works.
  • Consente a un server di consentire in modo esplicito alcune richieste tra origini rifiutando altre.Allows a server to explicitly allow some cross-origin requests while rejecting others.
  • È più sicuro e flessibile rispetto alle tecniche precedenti, ad esempio JSONP.Is safer and more flexible than earlier techniques, such as JSONP.

Visualizzare o scaricare il codice di esempio (procedura per il download)View or download sample code (how to download)

Stessa origineSame origin

Due URL hanno la stessa origine se hanno schemi, host e porte identici (RFC 6454).Two URLs have the same origin if they have identical schemes, hosts, and ports (RFC 6454).

Questi due URL hanno la stessa origine:These two URLs have the same origin:

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

Questi URL hanno origini diverse da quelle dei due URL precedenti:These URLs have different origins than the previous two URLs:

  • https://example.net – dominio diversohttps://example.net – Different domain
  • https://www.example.com/foo.html – sottodominio diversohttps://www.example.com/foo.html – Different subdomain
  • http://example.com/foo.html – schema diversohttp://example.com/foo.html – Different scheme
  • https://example.com:9000/foo.html – porta diversahttps://example.com:9000/foo.html – Different port

Internet Explorer non considera la porta durante il confronto delle origini.Internet Explorer doesn't consider the port when comparing origins.

CORS con criteri e middleware denominatiCORS with named policy and middleware

Il middleware CORS gestisce le richieste tra le origini.CORS Middleware handles cross-origin requests. Il codice seguente Abilita CORS per l'intera app con l'origine specificata: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();
    }
}

Il codice precedente:The preceding code:

La chiamata al metodo AddCors aggiunge i servizi CORS al contenitore del servizio dell'app: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);
}

Per ulteriori informazioni, vedere Opzioni dei criteri CORS in questo documento.For more information, see CORS policy options in this document .

Il metodo CorsPolicyBuilder può concatenare i metodi, come illustrato nel codice seguente: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);
}

Nota: l'URL non deve contenere una barra finale (/).Note: The URL must not contain a trailing slash (/). Se l'URL termina con /, il confronto restituisce false e non viene restituita alcuna intestazione.If the URL terminates with /, the comparison returns false and no header is returned.

Applicare i criteri di CORS a tutti gli endpointApply CORS policies to all endpoints

Il codice seguente applica i criteri di CORS a tutti gli endpoint di app tramite il middleware CORS:The following code applies CORS policies to all the apps endpoints via CORS Middleware:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    // Preceding code omitted.
    app.UseRouting();

    app.UseCors();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });

    // Following code omitted.
}

Avviso

Con il routing dell'endpoint è necessario configurare il middleware CORS per l'esecuzione tra le chiamate a UseRouting e UseEndpoints.With endpoint routing, the CORS middleware must be configured to execute between the calls to UseRouting and UseEndpoints. Una configurazione non corretta causerà il corretto funzionamento del middleware.Incorrect configuration will cause the middleware to stop functioning correctly.

Per applicare i criteri di CORS a livello di pagina/controller/azione , vedere Enable CORS in Razor Pages, Controllers e Action Methods .See Enable CORS in Razor Pages, controllers, and action methods to apply CORS policy at the page/controller/action level.

Vedere test CORS per istruzioni sul test del codice precedente.See Test CORS for instructions on testing the preceding code.

Abilitare cors con routing degli endpointEnable Cors with endpoint routing

Con il routing degli endpoint, è possibile abilitare CORS in base all'endpoint usando il set RequireCors di metodi di estensione.With endpoint routing, CORS can be enabled on a per-endpoint basis using the RequireCors set of extension methods.

app.UseEndpoints(endpoints =>
{
  endpoints.MapGet("/echo", async context => context.Response.WriteAsync("echo"))
    .RequireCors("policy-name");
});

Analogamente, è anche possibile abilitare CORS per tutti i controller:Similarly, CORS can also be enabled for all controllers:

app.UseEndpoints(endpoints =>
{
  endpoints.MapControllers().RequireCors("policy-name");
});

Abilita CORS con attributiEnable CORS with attributes

L'attributo [EnableCors] fornisce un'alternativa all'applicazione di CORS a livello globale.The [EnableCors] attribute provides an alternative to applying CORS globally. L'attributo [EnableCors] Abilita CORS per i punti finali selezionati, anziché tutti i punti finali.The [EnableCors] attribute enables CORS for selected end points, rather than all end points.

Utilizzare [EnableCors] per specificare i criteri predefiniti e [EnableCors("{Policy String}")] per specificare un criterio.Use [EnableCors] to specify the default policy and [EnableCors("{Policy String}")] to specify a policy.

L'attributo [EnableCors] può essere applicato a:The [EnableCors] attribute can be applied to:

  • PageModel pagina RazorRazor Page PageModel
  • ControllerController
  • Metodo di azione del controllerController action method

È possibile applicare criteri diversi a controller/pagina-modello/azione con l'attributo [EnableCors].You can apply different policies to controller/page-model/action with the [EnableCors] attribute. Quando l'attributo [EnableCors] viene applicato a controller/modello di pagina/Metodo di azione e CORS è abilitato nel middleware, vengono applicati entrambi i criteri.When the [EnableCors] attribute is applied to a controllers/page-model/action method, and CORS is enabled in middleware, both policies are applied. È consigliabile evitare di combinare i criteri.We recommend against combining policies. Usare il middleware o l'attributo [EnableCors], non entrambi nella stessa app.Use the [EnableCors] attribute or middleware, not both in the same app.

Il codice seguente applica un criterio diverso a ogni metodo: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();
        }
    }
}

Il codice seguente crea un criterio predefinito CORS e un criterio denominato "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();
    }
}

Disabilitare CORSDisable CORS

L'attributo [DisableCors] Disabilita CORS per il controller, il modello di pagina o l'azione.The [DisableCors] attribute disables CORS for the controller/page-model/action.

Opzioni dei criteri di CORSCORS policy options

In questa sezione vengono descritte le varie opzioni che è possibile impostare in un criterio CORS:This section describes the various options that can be set in a CORS policy:

AddPolicy viene chiamato Startup.ConfigureServices.AddPolicy is called in Startup.ConfigureServices. Per alcune opzioni, può essere utile leggere prima la sezione come funziona CORS .For some options, it may be helpful to read the How CORS works section first.

Imposta le origini consentiteSet the allowed origins

AllowAnyOrigin – consente richieste CORS da tutte le origini con qualsiasi schema (http o https).AllowAnyOrigin – Allows CORS requests from all origins with any scheme (http or https). AllowAnyOrigin non è sicuro perché qualsiasi sito Web può effettuare richieste tra origini per l'app.AllowAnyOrigin is insecure because any website can make cross-origin requests to the app.

Nota

La specifica di AllowAnyOrigin e AllowCredentials è una configurazione non sicura e può comportare la falsa richiesta tra siti.Specifying AllowAnyOrigin and AllowCredentials is an insecure configuration and can result in cross-site request forgery. Il servizio CORS restituisce una risposta CORS non valida quando un'app è configurata con entrambi i metodi.The CORS service returns an invalid CORS response when an app is configured with both methods.

AllowAnyOrigin influiscono sulle richieste preliminari e sull'intestazione Access-Control-Allow-Origin.AllowAnyOrigin affects preflight requests and the Access-Control-Allow-Origin header. Per ulteriori informazioni, vedere la sezione preflight requests .For more information, see the Preflight requests section.

SetIsOriginAllowedToAllowWildcardSubdomains – imposta la proprietà IsOriginAllowed del criterio in modo che sia una funzione che consente alle origini di corrispondere a un dominio con caratteri jolly configurato durante la valutazione se l'origine è consentita.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();
    });

Impostare i metodi HTTP consentitiSet the allowed HTTP methods

AllowAnyMethod:AllowAnyMethod:

  • Consente qualsiasi metodo HTTP:Allows any HTTP method:
  • Influiscono sulle richieste preliminari e sull'intestazione Access-Control-Allow-Methods.Affects preflight requests and the Access-Control-Allow-Methods header. Per ulteriori informazioni, vedere la sezione preflight requests .For more information, see the Preflight requests section.

Impostare le intestazioni della richiesta consentitaSet the allowed request headers

Per consentire l'invio di intestazioni specifiche in una richiesta CORS, denominate intestazioni richiesta autore, chiamare WithHeaders e specificare le intestazioni consentite: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");
    });

Per consentire tutte le intestazioni di richiesta di autore, chiamare AllowAnyHeader:To allow all author request headers, call AllowAnyHeader:

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

Questa impostazione influiscono sulle richieste preliminari e sull'intestazione Access-Control-Request-Headers.This setting affects preflight requests and the Access-Control-Request-Headers header. Per ulteriori informazioni, vedere la sezione preflight requests .For more information, see the Preflight requests section.

Un criterio middleware CORS corrisponde a intestazioni specifiche specificate da WithHeaders è possibile solo quando le intestazioni inviate in Access-Control-Request-Headers corrispondono esattamente alle intestazioni indicate in 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.

Si consideri, ad esempio, un'app configurata come segue:For instance, consider an app configured as follows:

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

Il middleware CORS rifiuta una richiesta preliminare con l'intestazione della richiesta seguente, perché Content-Language (HeaderNames. ContentLanguage) non è elencato in 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

L'app restituisce una risposta 200 OK , ma non invia le intestazioni CORS.The app returns a 200 OK response but doesn't send the CORS headers back. Pertanto, il browser non tenta di eseguire la richiesta tra origini.Therefore, the browser doesn't attempt the cross-origin request.

Impostare le intestazioni di risposta esposteSet the exposed response headers

Per impostazione predefinita, il browser non espone tutte le intestazioni di risposta all'app.By default, the browser doesn't expose all of the response headers to the app. Per altre informazioni, vedere la pagina relativa alla condivisione delle risorse tra le origini W3C (terminologia): intestazione della risposta semplice.For more information, see W3C Cross-Origin Resource Sharing (Terminology): Simple Response Header.

Le intestazioni di risposta disponibili per impostazione predefinita sono:The response headers that are available by default are:

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

La specifica CORS chiama queste intestazioni di risposta semplici.The CORS specification calls these headers simple response headers. Per rendere disponibili altre intestazioni per l'app, chiamare WithExposedHeaders:To make other headers available to the app, call WithExposedHeaders:

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

Credenziali nelle richieste tra le originiCredentials in cross-origin requests

Le credenziali richiedono una gestione speciale in una richiesta CORS.Credentials require special handling in a CORS request. Per impostazione predefinita, il browser non invia le credenziali con una richiesta tra le origini.By default, the browser doesn't send credentials with a cross-origin request. Le credenziali includono i cookie e gli schemi di autenticazione HTTP.Credentials include cookies and HTTP authentication schemes. Per inviare le credenziali con una richiesta tra le origini, il client deve impostare XMLHttpRequest.withCredentials su true.To send credentials with a cross-origin request, the client must set XMLHttpRequest.withCredentials to true.

Utilizzando direttamente XMLHttpRequest:Using XMLHttpRequest directly:

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

Uso di jQuery:Using jQuery:

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

Uso dell' API fetch:Using the Fetch API:

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

Il server deve consentire le credenziali.The server must allow the credentials. Per consentire le credenziali tra le origini, chiamare AllowCredentials:To allow cross-origin credentials, call AllowCredentials:

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

La risposta HTTP include un'intestazione Access-Control-Allow-Credentials, che indica al browser che il server consente le credenziali per una richiesta tra le origini.The HTTP response includes an Access-Control-Allow-Credentials header, which tells the browser that the server allows credentials for a cross-origin request.

Se il browser invia le credenziali, ma la risposta non include un'intestazione Access-Control-Allow-Credentials valida, il browser non espone la risposta all'app e la richiesta tra le origini ha esito negativo.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.

Consentire le credenziali tra le origini costituisce un rischio per la sicurezza.Allowing cross-origin credentials is a security risk. Un sito Web in un altro dominio può inviare le credenziali dell'utente che ha eseguito l'accesso all'app per conto dell'utente senza la conoscenza dell'utente.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.

La specifica CORS indica inoltre che l'impostazione delle origini per "*" (tutte le origini) non è valida se è presente l'intestazione del Access-Control-Allow-Credentials.The CORS specification also states that setting origins to "*" (all origins) is invalid if the Access-Control-Allow-Credentials header is present.

Richieste preliminariPreflight requests

Per alcune richieste CORS, il browser invia una richiesta aggiuntiva prima di effettuare la richiesta effettiva.For some CORS requests, the browser sends an additional request before making the actual request. Questa richiesta è detta richiesta preliminare.This request is called a preflight request. Il browser può ignorare la richiesta preliminare se vengono soddisfatte le condizioni seguenti:The browser can skip the preflight request if the following conditions are true:

  • Il metodo di richiesta è GET, HEAD o POST.The request method is GET, HEAD, or POST.
  • L'app non imposta intestazioni di richiesta diverse da Accept, Accept-Language, Content-Language, Content-Typeo Last-Event-ID.The app doesn't set request headers other than Accept, Accept-Language, Content-Language, Content-Type, or Last-Event-ID.
  • L'intestazione Content-Type, se impostata, presenta uno dei valori seguenti:The Content-Type header, if set, has one of the following values:
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain

La regola sulle intestazioni di richiesta impostate per la richiesta del client si applica alle intestazioni impostate dall'app chiamando setRequestHeader sull'oggetto XMLHttpRequest.The rule on request headers set for the client request applies to headers that the app sets by calling setRequestHeader on the XMLHttpRequest object. La specifica CORS chiama queste intestazioni di richiesta autoreintestazioni.The CORS specification calls these headers author request headers. La regola non si applica alle intestazioni che il browser può impostare, ad esempio User-Agent, Hosto Content-Length.The rule doesn't apply to headers the browser can set, such as User-Agent, Host, or Content-Length.

Di seguito è riportato un esempio di una richiesta preliminare: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

La richiesta pre-flight usa il metodo delle opzioni HTTP.The pre-flight request uses the HTTP OPTIONS method. Sono incluse due intestazioni speciali:It includes two special headers:

  • Access-Control-Request-Method: il metodo HTTP che verrà usato per la richiesta effettiva.Access-Control-Request-Method: The HTTP method that will be used for the actual request.
  • Access-Control-Request-Headers: elenco di intestazioni di richiesta impostate dall'app sulla richiesta effettiva.Access-Control-Request-Headers: A list of request headers that the app sets on the actual request. Come indicato in precedenza, non include le intestazioni impostate dal browser, ad esempio User-Agent.As stated earlier, this doesn't include headers that the browser sets, such as User-Agent.

Una richiesta preliminare CORS può includere un'intestazione Access-Control-Request-Headers, che indica al server le intestazioni inviate con la richiesta effettiva.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.

Per consentire intestazioni specifiche, chiamare WithHeaders:To allow specific headers, call WithHeaders:

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

Per consentire tutte le intestazioni di richiesta di autore, chiamare AllowAnyHeader:To allow all author request headers, call AllowAnyHeader:

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

I browser non sono completamente coerenti nell'impostazione Access-Control-Request-Headers.Browsers aren't entirely consistent in how they set Access-Control-Request-Headers. Se si impostano le intestazioni su un valore diverso da "*" (o si utilizza AllowAnyHeader), è necessario includere almeno Accept, Content-Typee Origin, oltre a eventuali intestazioni personalizzate che si desidera supportare.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.

Di seguito è riportato un esempio di risposta alla richiesta preliminare (presupponendo che il server consenta la richiesta):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

La risposta include un'intestazione Access-Control-Allow-Methods che elenca i metodi consentiti e, facoltativamente, un'intestazione Access-Control-Allow-Headers, che elenca le intestazioni consentite.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. Se la richiesta preliminare ha esito positivo, il browser invia la richiesta effettiva.If the preflight request succeeds, the browser sends the actual request.

Se la richiesta preliminare viene negata, l'app restituisce una risposta 200 OK , ma non invia le intestazioni CORS.If the preflight request is denied, the app returns a 200 OK response but doesn't send the CORS headers back. Pertanto, il browser non tenta di eseguire la richiesta tra origini.Therefore, the browser doesn't attempt the cross-origin request.

Imposta la data di scadenza preliminareSet the preflight expiration time

L'intestazione Access-Control-Max-Age specifica per quanto tempo la risposta alla richiesta preliminare può essere memorizzata nella cache.The Access-Control-Max-Age header specifies how long the response to the preflight request can be cached. Per impostare questa intestazione, chiamare SetPreflightMaxAge:To set this header, call SetPreflightMaxAge:

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

Funzionamento di CORSHow CORS works

In questa sezione viene descritto cosa accade in una richiesta CORS al livello dei messaggi HTTP.This section describes what happens in a CORS request at the level of the HTTP messages.

  • CORS non è una funzionalità di sicurezza.CORS is not a security feature. CORS è uno standard W3C che consente a un server di ridurre i criteri della stessa origine.CORS is a W3C standard that allows a server to relax the same-origin policy.
    • Ad esempio, un attore malintenzionato potrebbe usare Impedisci lo scripting tra siti (XSS) per il sito ed eseguire una richiesta tra siti al sito abilitato per CORS per rubare le informazioni.For example, a malicious actor could use Prevent Cross-Site Scripting (XSS) against your site and execute a cross-site request to their CORS enabled site to steal information.
  • L'API non è più sicura consentendo CORS.Your API is not safer by allowing CORS.
    • Il client (browser) deve applicare CORS.It's up to the client (browser) to enforce CORS. Il server esegue la richiesta e restituisce la risposta, ovvero il client che restituisce un errore e blocca la risposta.The server executes the request and returns the response, it's the client that returns an error and blocks the response. Uno degli strumenti seguenti, ad esempio, visualizzerà la risposta del server:For example, any of the following tools will display the server response:
  • Si tratta di un modo per consentire a un server di consentire ai browser di eseguire una richiesta dell' API di recupero o di XHR tra le origini, che altrimenti sarebbe proibita.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.
    • I browser (senza CORS) non possono eseguire richieste tra le origini.Browsers (without CORS) can't do cross-origin requests. Prima di CORS, JSONP è stato usato per aggirare questa restrizione.Before CORS, JSONP was used to circumvent this restriction. JSONP non usa XHR, usa il tag <script> per ricevere la risposta.JSONP doesn't use XHR, it uses the <script> tag to receive the response. Gli script possono essere caricati tra le origini.Scripts are allowed to be loaded cross-origin.

La specifica CORS ha introdotto diverse nuove intestazioni HTTP che consentono richieste tra le origini.The CORS specification introduced several new HTTP headers that enable cross-origin requests. Se un browser supporta CORS, queste intestazioni vengono impostate automaticamente per le richieste tra le origini.If a browser supports CORS, it sets these headers automatically for cross-origin requests. Il codice JavaScript personalizzato non è necessario per abilitare CORS.Custom JavaScript code isn't required to enable CORS.

Di seguito è riportato un esempio di richiesta tra le origini.The following is an example of a cross-origin request. L'intestazione Origin fornisce il dominio del sito che sta effettuando la richiesta.The Origin header provides the domain of the site that's making the request. L'intestazione Origin è obbligatoria e deve essere diversa dall'host.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

Se il server consente la richiesta, imposta l'intestazione Access-Control-Allow-Origin nella risposta.If the server allows the request, it sets the Access-Control-Allow-Origin header in the response. Il valore di questa intestazione corrisponde all'intestazione Origin dalla richiesta o è il valore del carattere jolly "*", che indica che è consentita un'origine: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

Se la risposta non include l'intestazione Access-Control-Allow-Origin, la richiesta tra le origini ha esito negativo.If the response doesn't include the Access-Control-Allow-Origin header, the cross-origin request fails. In particolare, il browser non consente la richiesta.Specifically, the browser disallows the request. Anche se il server restituisce una risposta con esito positivo, il browser non rende disponibile la risposta all'app client.Even if the server returns a successful response, the browser doesn't make the response available to the client app.

Testare CORSTest CORS

Per testare CORS:To test CORS:

  1. Creare un progetto API.Create an API project. In alternativa, è possibile scaricare l'esempio.Alternatively, you can download the sample.
  2. Abilitare CORS usando uno degli approcci descritti in questo documento.Enable CORS using one of the approaches in this document. Ad esempio,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();
}

Avviso

WithOrigins("https://localhost:<port>"); deve essere usato solo per il test di un'app di esempio simile al codice di esempioper il download.WithOrigins("https://localhost:<port>"); should only be used for testing a sample app similar to the download sample code.

  1. Creare un progetto di app Web (Razor Pages o MVC).Create a web app project (Razor Pages or MVC). Nell'esempio viene utilizzato Razor Pages.The sample uses Razor Pages. È possibile creare l'app Web nella stessa soluzione del progetto API.You can create the web app in the same solution as the API project.
  2. Aggiungere il codice evidenziato seguente al file 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. Nel codice precedente sostituire url: 'https://<web app>.azurewebsites.net/api/values/1', con l'URL dell'app distribuita.In the preceding code, replace url: 'https://<web app>.azurewebsites.net/api/values/1', with the URL to the deployed app.

  2. Distribuire il progetto API.Deploy the API project. Ad esempio, eseguire la distribuzione in Azure.For example, deploy to Azure.

  3. Eseguire l'app Razor Pages o MVC dal desktop e fare clic sul pulsante test .Run the Razor Pages or MVC app from the desktop and click on the Test button. Usare gli strumenti F12 per esaminare i messaggi di errore.Use the F12 tools to review error messages.

  4. Rimuovere l'origine localhost da WithOrigins e distribuire l'app.Remove the localhost origin from WithOrigins and deploy the app. In alternativa, eseguire l'app client con una porta diversa.Alternatively, run the client app with a different port. Ad esempio, eseguire da Visual Studio.For example, run from Visual Studio.

  5. Eseguire il test con l'app client.Test with the client app. Gli errori CORS restituiscono un errore, ma il messaggio di errore non è disponibile per JavaScript.CORS failures return an error, but the error message isn't available to JavaScript. Usare la scheda console negli strumenti F12 per visualizzare l'errore.Use the console tab in the F12 tools to see the error. A seconda del browser, viene ricevuto un errore (nella console strumenti F12) simile al seguente:Depending on the browser, you get an error (in the F12 tools console) similar to the following:

    • Uso di Microsoft Edge:Using Microsoft Edge:

      SEC7120: [CORS] la https://localhost:44375 di origine non ha trovato https://localhost:44375 nell'intestazione della risposta Access-Control-Allow-Origin per la risorsa tra le origini in 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

    • Uso di Chrome:Using Chrome:

      L'accesso a XMLHttpRequest in https://webapi.azurewebsites.net/api/values/1 dalla https://localhost:44375 di origine è stato bloccato dal criterio CORS: non è presente alcuna intestazione ' Access-Control-Allow-Origin ' nella risorsa richiesta.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.

Gli endpoint abilitati per CORS possono essere testati con uno strumento, ad esempio Fiddler o postazione.CORS-enabled endpoints can be tested with a tool, such as Fiddler or Postman. Quando si utilizza uno strumento, l'origine della richiesta specificata dall'intestazione Origin deve essere diversa dall'host che riceve la richiesta.When using a tool, the origin of the request specified by the Origin header must differ from the host receiving the request. Se la richiesta non è tra origini basate sul valore dell'intestazione Origin:If the request isn't cross-origin based on the value of the Origin header:

  • Non è necessario che il middleware CORS elabori la richiesta.There's no need for CORS Middleware to process the request.
  • Le intestazioni CORS non vengono restituite nella risposta.CORS headers aren't returned in the response.

CORS in IISCORS in IIS

Quando si esegue la distribuzione in IIS, CORS deve essere eseguito prima dell'autenticazione di Windows se il server non è configurato per consentire l'accesso anonimo.When deploying to IIS, CORS has to run before Windows Authentication if the server isn't configured to allow anonymous access. Per supportare questo scenario, è necessario installare e configurare il modulo cors di IIS per l'app.To support this scenario, the IIS CORS module needs to be installed and configured for the app.

Risorse aggiuntiveAdditional resources

Di Rick AndersonBy Rick Anderson

Questo articolo illustra come abilitare CORS in un'app ASP.NET Core.This article shows how to enable CORS in an ASP.NET Core app.

La sicurezza del browser impedisce a una pagina Web di eseguire richieste a un dominio diverso da quello che ha gestito la pagina Web.Browser security prevents a web page from making requests to a different domain than the one that served the web page. Questa restrizione è detta criterio della stessa origine.This restriction is called the same-origin policy. Il criterio della stessa origine impedisce a un sito dannoso di leggere dati sensibili da un altro sito.The same-origin policy prevents a malicious site from reading sensitive data from another site. In alcuni casi potrebbe essere necessario consentire ad altri siti di effettuare richieste tra le origini all'app.Sometimes, you might want to allow other sites make cross-origin requests to your app. Per altre informazioni, vedere l' articolo relativo a Mozilla CORS.For more information, see the Mozilla CORS article.

Condivisione risorse tra le origini (CORS):Cross Origin Resource Sharing (CORS):

  • È uno standard W3C che consente a un server di ridurre i criteri della stessa origine.Is a W3C standard that allows a server to relax the same-origin policy.
  • Non è una funzionalità di sicurezza, CORS rilassa la sicurezza.Is not a security feature, CORS relaxes security. Un'API non è più sicura consentendo CORS.An API is not safer by allowing CORS. Per ulteriori informazioni, vedere funzionamento di CORS.For more information, see How CORS works.
  • Consente a un server di consentire in modo esplicito alcune richieste tra origini rifiutando altre.Allows a server to explicitly allow some cross-origin requests while rejecting others.
  • È più sicuro e flessibile rispetto alle tecniche precedenti, ad esempio JSONP.Is safer and more flexible than earlier techniques, such as JSONP.

Visualizzare o scaricare il codice di esempio (procedura per il download)View or download sample code (how to download)

Stessa origineSame origin

Due URL hanno la stessa origine se hanno schemi, host e porte identici (RFC 6454).Two URLs have the same origin if they have identical schemes, hosts, and ports (RFC 6454).

Questi due URL hanno la stessa origine:These two URLs have the same origin:

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

Questi URL hanno origini diverse da quelle dei due URL precedenti:These URLs have different origins than the previous two URLs:

  • https://example.net – dominio diversohttps://example.net – Different domain
  • https://www.example.com/foo.html – sottodominio diversohttps://www.example.com/foo.html – Different subdomain
  • http://example.com/foo.html – schema diversohttp://example.com/foo.html – Different scheme
  • https://example.com:9000/foo.html – porta diversahttps://example.com:9000/foo.html – Different port

Internet Explorer non considera la porta durante il confronto delle origini.Internet Explorer doesn't consider the port when comparing origins.

CORS con criteri e middleware denominatiCORS with named policy and middleware

Il middleware CORS gestisce le richieste tra le origini.CORS Middleware handles cross-origin requests. Il codice seguente Abilita CORS per l'intera app con l'origine specificata: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();
    }
}

Il codice precedente:The preceding code:

La chiamata al metodo AddCors aggiunge i servizi CORS al contenitore del servizio dell'app: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);
}

Per ulteriori informazioni, vedere Opzioni dei criteri CORS in questo documento.For more information, see CORS policy options in this document .

Il metodo CorsPolicyBuilder può concatenare i metodi, come illustrato nel codice seguente: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);
}

Nota: l'URL non deve contenere una barra finale (/).Note: The URL must not contain a trailing slash (/). Se l'URL termina con /, il confronto restituisce false e non viene restituita alcuna intestazione.If the URL terminates with /, the comparison returns false and no header is returned.

Il codice seguente applica i criteri di CORS a tutti gli endpoint di app tramite il middleware 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();
}

Nota: è necessario chiamare UseCors prima di UseMvc.Note: UseCors must be called before UseMvc.

Per applicare i criteri di CORS a livello di pagina/controller/azione , vedere Enable CORS in Razor Pages, Controllers e Action Methods .See Enable CORS in Razor Pages, controllers, and action methods to apply CORS policy at the page/controller/action level.

Vedere test CORS per istruzioni sul test del codice precedente.See Test CORS for instructions on testing the preceding code.

Abilita CORS con attributiEnable CORS with attributes

L'attributo [EnableCors] fornisce un'alternativa all'applicazione di CORS a livello globale.The [EnableCors] attribute provides an alternative to applying CORS globally. L'attributo [EnableCors] Abilita CORS per i punti finali selezionati, anziché tutti i punti finali.The [EnableCors] attribute enables CORS for selected end points, rather than all end points.

Utilizzare [EnableCors] per specificare i criteri predefiniti e [EnableCors("{Policy String}")] per specificare un criterio.Use [EnableCors] to specify the default policy and [EnableCors("{Policy String}")] to specify a policy.

L'attributo [EnableCors] può essere applicato a:The [EnableCors] attribute can be applied to:

  • PageModel pagina RazorRazor Page PageModel
  • ControllerController
  • Metodo di azione del controllerController action method

È possibile applicare criteri diversi a controller/pagina-modello/azione con l'attributo [EnableCors].You can apply different policies to controller/page-model/action with the [EnableCors] attribute. Quando l'attributo [EnableCors] viene applicato a controller/modello di pagina/Metodo di azione e CORS è abilitato nel middleware, vengono applicati entrambi i criteri.When the [EnableCors] attribute is applied to a controllers/page-model/action method, and CORS is enabled in middleware, both policies are applied. È consigliabile evitare di combinare i criteri.We recommend against combining policies. Usare il middleware o l'attributo [EnableCors], non entrambi nella stessa app.Use the [EnableCors] attribute or middleware, not both in the same app.

Il codice seguente applica un criterio diverso a ogni metodo: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();
        }
    }
}

Il codice seguente crea un criterio predefinito CORS e un criterio denominato "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();
    }
}

Disabilitare CORSDisable CORS

L'attributo [DisableCors] Disabilita CORS per il controller, il modello di pagina o l'azione.The [DisableCors] attribute disables CORS for the controller/page-model/action.

Opzioni dei criteri di CORSCORS policy options

In questa sezione vengono descritte le varie opzioni che è possibile impostare in un criterio CORS:This section describes the various options that can be set in a CORS policy:

AddPolicy viene chiamato Startup.ConfigureServices.AddPolicy is called in Startup.ConfigureServices. Per alcune opzioni, può essere utile leggere prima la sezione come funziona CORS .For some options, it may be helpful to read the How CORS works section first.

Imposta le origini consentiteSet the allowed origins

AllowAnyOrigin – consente richieste CORS da tutte le origini con qualsiasi schema (http o https).AllowAnyOrigin – Allows CORS requests from all origins with any scheme (http or https). AllowAnyOrigin non è sicuro perché qualsiasi sito Web può effettuare richieste tra origini per l'app.AllowAnyOrigin is insecure because any website can make cross-origin requests to the app.

Nota

La specifica di AllowAnyOrigin e AllowCredentials è una configurazione non sicura e può comportare la falsa richiesta tra siti.Specifying AllowAnyOrigin and AllowCredentials is an insecure configuration and can result in cross-site request forgery. Per un'app sicura, specificare un elenco esatto di origini se il client deve autorizzare se stesso ad accedere alle risorse del server.For a secure app, specify an exact list of origins if the client must authorize itself to access server resources.

AllowAnyOrigin influiscono sulle richieste preliminari e sull'intestazione Access-Control-Allow-Origin.AllowAnyOrigin affects preflight requests and the Access-Control-Allow-Origin header. Per ulteriori informazioni, vedere la sezione preflight requests .For more information, see the Preflight requests section.

SetIsOriginAllowedToAllowWildcardSubdomains – imposta la proprietà IsOriginAllowed del criterio in modo che sia una funzione che consente alle origini di corrispondere a un dominio con caratteri jolly configurato durante la valutazione se l'origine è consentita.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();
    });

Impostare i metodi HTTP consentitiSet the allowed HTTP methods

AllowAnyMethod:AllowAnyMethod:

  • Consente qualsiasi metodo HTTP:Allows any HTTP method:
  • Influiscono sulle richieste preliminari e sull'intestazione Access-Control-Allow-Methods.Affects preflight requests and the Access-Control-Allow-Methods header. Per ulteriori informazioni, vedere la sezione preflight requests .For more information, see the Preflight requests section.

Impostare le intestazioni della richiesta consentitaSet the allowed request headers

Per consentire l'invio di intestazioni specifiche in una richiesta CORS, denominate intestazioni richiesta autore, chiamare WithHeaders e specificare le intestazioni consentite: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");
    });

Per consentire tutte le intestazioni di richiesta di autore, chiamare AllowAnyHeader:To allow all author request headers, call AllowAnyHeader:

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

Questa impostazione influiscono sulle richieste preliminari e sull'intestazione Access-Control-Request-Headers.This setting affects preflight requests and the Access-Control-Request-Headers header. Per ulteriori informazioni, vedere la sezione preflight requests .For more information, see the Preflight requests section.

Il middleware CORS consente sempre di inviare quattro intestazioni nel Access-Control-Request-Headers indipendentemente dai valori configurati in CorsPolicy. Headers.CORS Middleware always allows four headers in the Access-Control-Request-Headers to be sent regardless of the values configured in CorsPolicy.Headers. Questo elenco di intestazioni include:This list of headers includes:

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

Si consideri, ad esempio, un'app configurata come segue:For instance, consider an app configured as follows:

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

Il middleware CORS risponde correttamente a una richiesta preliminare con la seguente intestazione di richiesta perché Content-Language è sempre consentita:CORS Middleware responds successfully to a preflight request with the following request header because Content-Language is always whitelisted:

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

Impostare le intestazioni di risposta esposteSet the exposed response headers

Per impostazione predefinita, il browser non espone tutte le intestazioni di risposta all'app.By default, the browser doesn't expose all of the response headers to the app. Per altre informazioni, vedere la pagina relativa alla condivisione delle risorse tra le origini W3C (terminologia): intestazione della risposta semplice.For more information, see W3C Cross-Origin Resource Sharing (Terminology): Simple Response Header.

Le intestazioni di risposta disponibili per impostazione predefinita sono:The response headers that are available by default are:

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

La specifica CORS chiama queste intestazioni di risposta semplici.The CORS specification calls these headers simple response headers. Per rendere disponibili altre intestazioni per l'app, chiamare WithExposedHeaders:To make other headers available to the app, call WithExposedHeaders:

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

Credenziali nelle richieste tra le originiCredentials in cross-origin requests

Le credenziali richiedono una gestione speciale in una richiesta CORS.Credentials require special handling in a CORS request. Per impostazione predefinita, il browser non invia le credenziali con una richiesta tra le origini.By default, the browser doesn't send credentials with a cross-origin request. Le credenziali includono i cookie e gli schemi di autenticazione HTTP.Credentials include cookies and HTTP authentication schemes. Per inviare le credenziali con una richiesta tra le origini, il client deve impostare XMLHttpRequest.withCredentials su true.To send credentials with a cross-origin request, the client must set XMLHttpRequest.withCredentials to true.

Utilizzando direttamente XMLHttpRequest:Using XMLHttpRequest directly:

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

Uso di jQuery:Using jQuery:

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

Uso dell' API fetch:Using the Fetch API:

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

Il server deve consentire le credenziali.The server must allow the credentials. Per consentire le credenziali tra le origini, chiamare AllowCredentials:To allow cross-origin credentials, call AllowCredentials:

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

La risposta HTTP include un'intestazione Access-Control-Allow-Credentials, che indica al browser che il server consente le credenziali per una richiesta tra le origini.The HTTP response includes an Access-Control-Allow-Credentials header, which tells the browser that the server allows credentials for a cross-origin request.

Se il browser invia le credenziali, ma la risposta non include un'intestazione Access-Control-Allow-Credentials valida, il browser non espone la risposta all'app e la richiesta tra le origini ha esito negativo.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.

Consentire le credenziali tra le origini costituisce un rischio per la sicurezza.Allowing cross-origin credentials is a security risk. Un sito Web in un altro dominio può inviare le credenziali dell'utente che ha eseguito l'accesso all'app per conto dell'utente senza la conoscenza dell'utente.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.

La specifica CORS indica inoltre che l'impostazione delle origini per "*" (tutte le origini) non è valida se è presente l'intestazione del Access-Control-Allow-Credentials.The CORS specification also states that setting origins to "*" (all origins) is invalid if the Access-Control-Allow-Credentials header is present.

Richieste preliminariPreflight requests

Per alcune richieste CORS, il browser invia una richiesta aggiuntiva prima di effettuare la richiesta effettiva.For some CORS requests, the browser sends an additional request before making the actual request. Questa richiesta è detta richiesta preliminare.This request is called a preflight request. Il browser può ignorare la richiesta preliminare se vengono soddisfatte le condizioni seguenti:The browser can skip the preflight request if the following conditions are true:

  • Il metodo di richiesta è GET, HEAD o POST.The request method is GET, HEAD, or POST.
  • L'app non imposta intestazioni di richiesta diverse da Accept, Accept-Language, Content-Language, Content-Typeo Last-Event-ID.The app doesn't set request headers other than Accept, Accept-Language, Content-Language, Content-Type, or Last-Event-ID.
  • L'intestazione Content-Type, se impostata, presenta uno dei valori seguenti:The Content-Type header, if set, has one of the following values:
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain

La regola sulle intestazioni di richiesta impostate per la richiesta del client si applica alle intestazioni impostate dall'app chiamando setRequestHeader sull'oggetto XMLHttpRequest.The rule on request headers set for the client request applies to headers that the app sets by calling setRequestHeader on the XMLHttpRequest object. La specifica CORS chiama queste intestazioni di richiesta autoreintestazioni.The CORS specification calls these headers author request headers. La regola non si applica alle intestazioni che il browser può impostare, ad esempio User-Agent, Hosto Content-Length.The rule doesn't apply to headers the browser can set, such as User-Agent, Host, or Content-Length.

Di seguito è riportato un esempio di una richiesta preliminare: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

La richiesta pre-flight usa il metodo delle opzioni HTTP.The pre-flight request uses the HTTP OPTIONS method. Sono incluse due intestazioni speciali:It includes two special headers:

  • Access-Control-Request-Method: il metodo HTTP che verrà usato per la richiesta effettiva.Access-Control-Request-Method: The HTTP method that will be used for the actual request.
  • Access-Control-Request-Headers: elenco di intestazioni di richiesta impostate dall'app sulla richiesta effettiva.Access-Control-Request-Headers: A list of request headers that the app sets on the actual request. Come indicato in precedenza, non include le intestazioni impostate dal browser, ad esempio User-Agent.As stated earlier, this doesn't include headers that the browser sets, such as User-Agent.

Una richiesta preliminare CORS può includere un'intestazione Access-Control-Request-Headers, che indica al server le intestazioni inviate con la richiesta effettiva.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.

Per consentire intestazioni specifiche, chiamare WithHeaders:To allow specific headers, call WithHeaders:

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

Per consentire tutte le intestazioni di richiesta di autore, chiamare AllowAnyHeader:To allow all author request headers, call AllowAnyHeader:

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

I browser non sono completamente coerenti nell'impostazione Access-Control-Request-Headers.Browsers aren't entirely consistent in how they set Access-Control-Request-Headers. Se si impostano le intestazioni su un valore diverso da "*" (o si utilizza AllowAnyHeader), è necessario includere almeno Accept, Content-Typee Origin, oltre a eventuali intestazioni personalizzate che si desidera supportare.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.

Di seguito è riportato un esempio di risposta alla richiesta preliminare (presupponendo che il server consenta la richiesta):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

La risposta include un'intestazione Access-Control-Allow-Methods che elenca i metodi consentiti e, facoltativamente, un'intestazione Access-Control-Allow-Headers, che elenca le intestazioni consentite.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. Se la richiesta preliminare ha esito positivo, il browser invia la richiesta effettiva.If the preflight request succeeds, the browser sends the actual request.

Se la richiesta preliminare viene negata, l'app restituisce una risposta 200 OK , ma non invia le intestazioni CORS.If the preflight request is denied, the app returns a 200 OK response but doesn't send the CORS headers back. Pertanto, il browser non tenta di eseguire la richiesta tra origini.Therefore, the browser doesn't attempt the cross-origin request.

Imposta la data di scadenza preliminareSet the preflight expiration time

L'intestazione Access-Control-Max-Age specifica per quanto tempo la risposta alla richiesta preliminare può essere memorizzata nella cache.The Access-Control-Max-Age header specifies how long the response to the preflight request can be cached. Per impostare questa intestazione, chiamare SetPreflightMaxAge:To set this header, call SetPreflightMaxAge:

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

Funzionamento di CORSHow CORS works

In questa sezione viene descritto cosa accade in una richiesta CORS al livello dei messaggi HTTP.This section describes what happens in a CORS request at the level of the HTTP messages.

  • CORS non è una funzionalità di sicurezza.CORS is not a security feature. CORS è uno standard W3C che consente a un server di ridurre i criteri della stessa origine.CORS is a W3C standard that allows a server to relax the same-origin policy.
    • Ad esempio, un attore malintenzionato potrebbe usare Impedisci lo scripting tra siti (XSS) per il sito ed eseguire una richiesta tra siti al sito abilitato per CORS per rubare le informazioni.For example, a malicious actor could use Prevent Cross-Site Scripting (XSS) against your site and execute a cross-site request to their CORS enabled site to steal information.
  • L'API non è più sicura consentendo CORS.Your API is not safer by allowing CORS.
    • Il client (browser) deve applicare CORS.It's up to the client (browser) to enforce CORS. Il server esegue la richiesta e restituisce la risposta, ovvero il client che restituisce un errore e blocca la risposta.The server executes the request and returns the response, it's the client that returns an error and blocks the response. Uno degli strumenti seguenti, ad esempio, visualizzerà la risposta del server:For example, any of the following tools will display the server response:
  • Si tratta di un modo per consentire a un server di consentire ai browser di eseguire una richiesta dell' API di recupero o di XHR tra le origini, che altrimenti sarebbe proibita.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.
    • I browser (senza CORS) non possono eseguire richieste tra le origini.Browsers (without CORS) can't do cross-origin requests. Prima di CORS, JSONP è stato usato per aggirare questa restrizione.Before CORS, JSONP was used to circumvent this restriction. JSONP non usa XHR, usa il tag <script> per ricevere la risposta.JSONP doesn't use XHR, it uses the <script> tag to receive the response. Gli script possono essere caricati tra le origini.Scripts are allowed to be loaded cross-origin.

La specifica CORS ha introdotto diverse nuove intestazioni HTTP che consentono richieste tra le origini.The CORS specification introduced several new HTTP headers that enable cross-origin requests. Se un browser supporta CORS, queste intestazioni vengono impostate automaticamente per le richieste tra le origini.If a browser supports CORS, it sets these headers automatically for cross-origin requests. Il codice JavaScript personalizzato non è necessario per abilitare CORS.Custom JavaScript code isn't required to enable CORS.

Di seguito è riportato un esempio di richiesta tra le origini.The following is an example of a cross-origin request. L'intestazione Origin fornisce il dominio del sito che sta effettuando la richiesta.The Origin header provides the domain of the site that's making the request. L'intestazione Origin è obbligatoria e deve essere diversa dall'host.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

Se il server consente la richiesta, imposta l'intestazione Access-Control-Allow-Origin nella risposta.If the server allows the request, it sets the Access-Control-Allow-Origin header in the response. Il valore di questa intestazione corrisponde all'intestazione Origin dalla richiesta o è il valore del carattere jolly "*", che indica che è consentita un'origine: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

Se la risposta non include l'intestazione Access-Control-Allow-Origin, la richiesta tra le origini ha esito negativo.If the response doesn't include the Access-Control-Allow-Origin header, the cross-origin request fails. In particolare, il browser non consente la richiesta.Specifically, the browser disallows the request. Anche se il server restituisce una risposta con esito positivo, il browser non rende disponibile la risposta all'app client.Even if the server returns a successful response, the browser doesn't make the response available to the client app.

Testare CORSTest CORS

Per testare CORS:To test CORS:

  1. Creare un progetto API.Create an API project. In alternativa, è possibile scaricare l'esempio.Alternatively, you can download the sample.
  2. Abilitare CORS usando uno degli approcci descritti in questo documento.Enable CORS using one of the approaches in this document. Ad esempio,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();
}

Avviso

WithOrigins("https://localhost:<port>"); deve essere usato solo per il test di un'app di esempio simile al codice di esempioper il download.WithOrigins("https://localhost:<port>"); should only be used for testing a sample app similar to the download sample code.

  1. Creare un progetto di app Web (Razor Pages o MVC).Create a web app project (Razor Pages or MVC). Nell'esempio viene utilizzato Razor Pages.The sample uses Razor Pages. È possibile creare l'app Web nella stessa soluzione del progetto API.You can create the web app in the same solution as the API project.
  2. Aggiungere il codice evidenziato seguente al file 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. Nel codice precedente sostituire url: 'https://<web app>.azurewebsites.net/api/values/1', con l'URL dell'app distribuita.In the preceding code, replace url: 'https://<web app>.azurewebsites.net/api/values/1', with the URL to the deployed app.

  2. Distribuire il progetto API.Deploy the API project. Ad esempio, eseguire la distribuzione in Azure.For example, deploy to Azure.

  3. Eseguire l'app Razor Pages o MVC dal desktop e fare clic sul pulsante test .Run the Razor Pages or MVC app from the desktop and click on the Test button. Usare gli strumenti F12 per esaminare i messaggi di errore.Use the F12 tools to review error messages.

  4. Rimuovere l'origine localhost da WithOrigins e distribuire l'app.Remove the localhost origin from WithOrigins and deploy the app. In alternativa, eseguire l'app client con una porta diversa.Alternatively, run the client app with a different port. Ad esempio, eseguire da Visual Studio.For example, run from Visual Studio.

  5. Eseguire il test con l'app client.Test with the client app. Gli errori CORS restituiscono un errore, ma il messaggio di errore non è disponibile per JavaScript.CORS failures return an error, but the error message isn't available to JavaScript. Usare la scheda console negli strumenti F12 per visualizzare l'errore.Use the console tab in the F12 tools to see the error. A seconda del browser, viene ricevuto un errore (nella console strumenti F12) simile al seguente:Depending on the browser, you get an error (in the F12 tools console) similar to the following:

    • Uso di Microsoft Edge:Using Microsoft Edge:

      SEC7120: [CORS] la https://localhost:44375 di origine non ha trovato https://localhost:44375 nell'intestazione della risposta Access-Control-Allow-Origin per la risorsa tra le origini in 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

    • Uso di Chrome:Using Chrome:

      L'accesso a XMLHttpRequest in https://webapi.azurewebsites.net/api/values/1 dalla https://localhost:44375 di origine è stato bloccato dal criterio CORS: non è presente alcuna intestazione ' Access-Control-Allow-Origin ' nella risorsa richiesta.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.

Gli endpoint abilitati per CORS possono essere testati con uno strumento, ad esempio Fiddler o postazione.CORS-enabled endpoints can be tested with a tool, such as Fiddler or Postman. Quando si utilizza uno strumento, l'origine della richiesta specificata dall'intestazione Origin deve essere diversa dall'host che riceve la richiesta.When using a tool, the origin of the request specified by the Origin header must differ from the host receiving the request. Se la richiesta non è tra origini basate sul valore dell'intestazione Origin:If the request isn't cross-origin based on the value of the Origin header:

  • Non è necessario che il middleware CORS elabori la richiesta.There's no need for CORS Middleware to process the request.
  • Le intestazioni CORS non vengono restituite nella risposta.CORS headers aren't returned in the response.

CORS in IISCORS in IIS

Quando si esegue la distribuzione in IIS, CORS deve essere eseguito prima dell'autenticazione di Windows se il server non è configurato per consentire l'accesso anonimo.When deploying to IIS, CORS has to run before Windows Authentication if the server isn't configured to allow anonymous access. Per supportare questo scenario, è necessario installare e configurare il modulo cors di IIS per l'app.To support this scenario, the IIS CORS module needs to be installed and configured for the app.

Risorse aggiuntiveAdditional resources