Come abilitare CORS in ASP.net Core WebAPI


190

Cosa sto cercando di fare

Ho un'API Web ASP.Net Core back-end ospitata su un piano gratuito di Azure (codice sorgente: https://github.com/killerrin/Portfolio-Backend ).

Ho anche un sito Web del cliente che desidero far utilizzare quell'API. L'applicazione client non sarà ospitata su Azure, ma piuttosto sarà ospitata su Github Pages o su un altro servizio di hosting Web a cui ho accesso. Per questo motivo i nomi di dominio non si allineano.

In questo caso, devo abilitare CORS sul lato API Web, tuttavia ho provato praticamente tutto per diverse ore e si sta rifiutando di funzionare.

Come ho l'installazione del client È solo un semplice client scritto in React.js. Sto chiamando le API tramite AJAX in Jquery. Il sito React funziona, quindi so che non è quello. La chiamata API Jquery funziona come ho confermato nel tentativo 1. Ecco come effettuare le chiamate

    var apiUrl = "http://andrewgodfroyportfolioapi.azurewebsites.net/api/Authentication";
    //alert(username + "|" + password + "|" + apiUrl);
    $.ajax({
        url: apiUrl,
        type: "POST",
        data: {
            username: username,
            password: password
        },
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function (response) {
            var authenticatedUser = JSON.parse(response);
            //alert("Data Loaded: " + authenticatedUser);
            if (onComplete != null) {
                onComplete(authenticatedUser);
            }
        },
        error: function (xhr, status, error) {
            //alert(xhr.responseText);
            if (onComplete != null) {
                onComplete(xhr.responseText);
            }
        }
    });

Quello che ho provato


Tentativo 1 - Il modo "corretto"

https://docs.microsoft.com/en-us/aspnet/core/security/cors

Ho seguito questo tutorial sul sito Web Microsoft fino a un T, provando tutte e 3 le opzioni per abilitarlo globalmente in Startup.cs, configurarlo su ogni controller e provarlo su ogni azione.

Seguendo questo metodo, Cross Domain funziona, ma solo su una singola azione su un singolo controller (da POST a AccountController). Per tutto il resto, il Microsoft.AspNetCore.Corsmiddleware rifiuta di impostare le intestazioni.

Ho installato Microsoft.AspNetCore.Corstramite NUGET e la versione è1.1.2

Ecco come l'ho installato in Startup.cs

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        // Add Cors
        services.AddCors(o => o.AddPolicy("MyPolicy", builder =>
        {
            builder.AllowAnyOrigin()
                   .AllowAnyMethod()
                   .AllowAnyHeader();
        }));

        // Add framework services.
        services.AddMvc();
        services.Configure<MvcOptions>(options =>
        {
            options.Filters.Add(new CorsAuthorizationFilterFactory("MyPolicy"));
        });

        ...
        ...
        ...
    }

    // This method gets called by the runtime. Use this method to configure 
    //the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env,
    ILoggerFactory loggerFactory)
    {
        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();

        // Enable Cors
        app.UseCors("MyPolicy");

        //app.UseMvcWithDefaultRoute();
        app.UseMvc();

        ...
        ...
        ...
    }

Come puoi vedere, sto facendo tutto come detto. Aggiungo Cors prima di MVC entrambe le volte, e quando non ha funzionato ho provato a mettere [EnableCors("MyPolicy")]su ogni controller così

[Route("api/[controller]")]
[EnableCors("MyPolicy")]
public class AdminController : Controller

Tentativo 2 - Bruto forzandolo

https://andrewlock.net/adding-default-security-headers-in-asp-net-core/

Dopo diverse ore di tentativi sul tentativo precedente, ho pensato che avrei provato a potenziarlo provando a impostare manualmente le intestazioni, costringendole a correre su ogni risposta. L'ho fatto seguendo questo tutorial su come aggiungere manualmente le intestazioni ad ogni risposta.

Queste sono le intestazioni che ho aggiunto

.AddCustomHeader("Access-Control-Allow-Origin", "*")
.AddCustomHeader("Access-Control-Allow-Methods", "*")
.AddCustomHeader("Access-Control-Allow-Headers", "*")
.AddCustomHeader("Access-Control-Max-Age", "86400")

Queste sono altre intestazioni che ho provato e che hanno fallito

.AddCustomHeader("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE")
.AddCustomHeader("Access-Control-Allow-Headers", "content-type, accept, X-PINGOTHER")
.AddCustomHeader("Access-Control-Allow-Headers", "X-PINGOTHER, Host, User-Agent, Accept, Accept: application/json, application/json, Accept-Language, Accept-Encoding, Access-Control-Request-Method, Access-Control-Request-Headers, Origin, Connection, Content-Type, Content-Type: application/json, Authorization, Connection, Origin, Referer")

Con questo metodo, le intestazioni Cross Site vengono correttamente applicate e vengono visualizzate nella mia console di sviluppo e in Postman. Il problema tuttavia è che mentre passa il Access-Control-Allow-Origincontrollo, il webbrowser lancia un sibilante adattamento (credo) Access-Control-Allow-Headersaffermando415 (Unsupported Media Type)

Quindi anche il metodo della forza bruta non funziona


Finalmente

Qualcuno ha ottenuto che funzioni e potrebbe dare una mano o essere in grado di indicarmi la giusta direzione?


MODIFICARE

Quindi, per far passare le chiamate API, ho dovuto smettere di usare JQuery e passare a un XMLHttpRequestformato Javascript puro .

Tentativo 1

Sono riuscito a farlo Microsoft.AspNetCore.Corsfunzionare seguendo la risposta di MindingData, ad eccezione del Configuremetodo che app.UseCorsprecede app.UseMvc.

Inoltre, quando combinato con la soluzione API Javascript options.AllowAnyOrigin()per il supporto con caratteri jolly ha iniziato a funzionare anche.

Tentativo 2

Quindi sono riuscito a far funzionare Attempt 2 (forzandolo bruto) ... con l'unica eccezione per cui Wildcard Access-Control-Allow-Originnon funziona e come tale devo impostare manualmente i domini che hanno accesso ad esso.

Ovviamente non è l'ideale poiché voglio solo che questa WebAPI sia aperta a tutti, ma almeno funziona per me su un sito separato, il che significa che è un inizio

app.UseSecurityHeadersMiddleware(new SecurityHeadersBuilder()
    .AddDefaultSecurePolicy()
    .AddCustomHeader("Access-Control-Allow-Origin", "http://localhost:3000")
    .AddCustomHeader("Access-Control-Allow-Methods", "OPTIONS, GET, POST, PUT, PATCH, DELETE")
    .AddCustomHeader("Access-Control-Allow-Headers", "X-PINGOTHER, Content-Type, Authorization"));

2
Per il tuo 415 (Unsupported Media Type)problema, imposta Content-Typeun'intestazione di richiesta su application/json.
Technetium,

5
Grazie per aver dedicato del tempo a scrivere una domanda così descrittiva.
user1007074

1
Se stai testando usando Postman, assicurati di impostare Origin su * o qualcosa per l'intestazione della richiesta, quindi il Tentativo 1 dovrebbe funzionare. Senza questa intestazione, Access-Control-Allow-Origin non verrà restituito nell'intestazione della risposta.
tala9999,

Risposte:


240

Poiché hai una politica CORS molto semplice (Consenti tutte le richieste dal dominio XXX), non è necessario renderlo così complicato. Prova a fare prima quanto segue (un'implementazione di base di CORS).

Se non lo hai già fatto, installa il pacchetto nuget CORS.

Install-Package Microsoft.AspNetCore.Cors

Nel metodo ConfigureServices di startup.cs, aggiungi i servizi CORS.

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(); // Make sure you call this previous to AddMvc
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

Quindi nel metodo Configura di startup.cs, aggiungi quanto segue:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    // Make sure you call this before calling app.UseMvc()
    app.UseCors(
        options => options.WithOrigins("http://example.com").AllowAnyMethod()
    );

    app.UseMvc();
}

Adesso provaci. Le politiche sono per quando si desidera politiche diverse per azioni diverse (ad esempio host diversi o intestazioni diverse). Per il tuo semplice esempio non ne hai davvero bisogno. Inizia con questo semplice esempio e modifica come è necessario da lì.

Ulteriori letture: http://dotnetcoretutorials.com/2017/01/03/enabling-cors-asp-net-core/


3
XMLHttpRequest non può caricare andrewgodfroyportfolioapi.azurewebsite.net/api/Authentication . La risposta alla richiesta di verifica preliminare non supera il controllo del controllo di accesso: non è presente alcuna intestazione "Access-Control-Allow-Origin" sulla risorsa richiesta. L'origine ' localhost: 3000 ' non può quindi accedere. La risposta aveva il codice di stato HTTP 415.
killerrin,

7
È improbabile che funzioni, quando ti registri app.UseCors DOPO `` app.UseMvc () `. I middleware vengono eseguiti nell'ordine in cui sono registrati
Tseng

24
usando app.UseCors prima di app.UseMvc, nel metodo Configura sembra funzionare. Per qualche ragione, la sequenza sembra avere importanza.
MrClan,

1
Per me, il problema più grande di CORS in 2.0 è che non dice cosa c'è che non va, ma non riesce a impostare le intestazioni CORS in silenzio. Nota : ricordati di aggiungere tutte le intestazioni richieste alla politica o fallirà (avevo il tipo di contenuto). Inoltre, cosa strana per me che il middleware CORS non interrompe l'elaborazione delle richieste, semplicemente informando nei registri che l'origine non è consentita e .. Passa ulteriormente la richiesta (l'ordine del middleware era corretto).
Andrii M4n0w4R,

2
Ho dovuto abilitare options.DisableHttpsRequirement();per far funzionare tutto questo. Sembra che con https le impostazioni cors non fossero applicabili.
Michael Brown,

210
  • In ConfigureServices aggiungere services.AddCors(); PRIMA di services.AddMvc ();

  • Aggiungi UseCors in Configura

     app.UseCors(builder => builder
         .AllowAnyOrigin()
         .AllowAnyMethod()
         .AllowAnyHeader());   
     app.UseMvc();

Il punto principale è che aggiungere app.UseCors, prima app.UseMvc().

Assicurarsi di dichiarare la funzionalità CORS prima di MVC in modo che il middleware si attivi prima che la pipeline MVC ottenga il controllo e termini la richiesta.

Dopo che il metodo sopra funziona, puoi cambiarlo configurando un ORIGIN specifico per accettare le chiamate api ed evitare di lasciare la tua API così aperta a chiunque

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(options => options.AddPolicy("ApiCorsPolicy", builder =>
    {
        builder.WithOrigins("http://localhost:4200").AllowAnyMethod().AllowAnyHeader();
    }));

    services.AddMvc();
}

Nel metodo di configurazione dire a CORS di utilizzare il criterio appena creato:

app.UseCors("ApiCorsPolicy");
app.UseMvc();

Ho appena trovato questo articolo compatto sull'argomento - https://dzone.com/articles/cors-in-net-core-net-core-security-part-vi


1
Questo funziona per me. codeproject.com/Articles/1150023/…
hubert17

17
Questo dovrebbe davvero ottenere più voti come un buon punto di "partenza". Nella mia esperienza di oltre 25 anni di programmazione, è sempre bello sapere come aprire le porte per assicurarsi che effettivamente "funzioni" e quindi chiudere / proteggere le cose secondo necessità.
Indy-Jones,

4
Solo per citare questo, in contrasto con Configure()l'ordine non è davvero importante qui all'internoConfigureServices()
B12Toaster

Ho usato il collegamento nell'Ulteriori Reader e quei passaggi hanno risolto questo errore. Non ero sicuro di dove posizionare queste modifiche (pensavo che l'API). Il collegamento ha confermato che devono essere inseriti nell'API. Grazie per l'aiuto. Stavo girando completamente le ruote con questo errore.
Richard,

1
Cordiali saluti - La specifica CORS afferma inoltre che l'impostazione dell'origine su "*" (tutte le origini) non è valida se è presente l'intestazione Access-Control-Allow-Credentials. Significa che non puoi usare AllowCredentials()con AllowAnyOrigin()come sopra. Per utilizzare AllowCredentials()è necessario impostare WithOrigins(). docs.microsoft.com/en-us/aspnet/core/security/…
Nick De Beer

28

Ho creato la mia classe di middleware che ha funzionato per me, penso che ci sia qualcosa di sbagliato con la classe di middleware core .net

public class CorsMiddleware
{
    private readonly RequestDelegate _next;

    public CorsMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public Task Invoke(HttpContext httpContext)
    {
        httpContext.Response.Headers.Add("Access-Control-Allow-Origin", "*");
        httpContext.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
        httpContext.Response.Headers.Add("Access-Control-Allow-Headers", "Content-Type, X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Date, X-Api-Version, X-File-Name");
        httpContext.Response.Headers.Add("Access-Control-Allow-Methods", "POST,GET,PUT,PATCH,DELETE,OPTIONS");
        return _next(httpContext);
    }
}

// Extension method used to add the middleware to the HTTP request pipeline.
public static class CorsMiddlewareExtensions
{
    public static IApplicationBuilder UseCorsMiddleware(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<CorsMiddleware>();
    }
}

e utilizzato in questo modo in startup.cs

app.UseCorsMiddleware();

Modo molto elegante di eseguire Access-Control-Allow-Origin.
Artur Poniedziałek,

Funziona su WebAPI e MVC e non ha dipendenze, grazie!
Joe,

Ero scettico anche su questo, ma ha funzionato per me. Ho provato praticamente ogni altro metodo per ottenere questo risultato che ho potuto trovare su Internet, ma qualunque cosa il server non rispondesse con le intestazioni di accesso. Questo ha funzionato alla grande. Sto eseguendo aspnetcore 2.1.
Giordania,

È necessario restituire le intestazioni cors solo se il client invia l'intestazione "Origine" nella richiesta. Nel CospMiddleware originale si presenta così:if (!context.Request.Headers.ContainsKey(CorsConstants.Origin)) return this._next(context);
Andrew Prigorshnev,

2
Forse "qualcosa di sbagliato con la classe middleware core .net" perché non aggiungi l'header "Origin" quando lo provi con il ricciolo o qualcosa del genere. I browser aggiungono automaticamente questa intestazione quando si effettua una richiesta nel codice js.
Andrew Prigorshnev,

18

Nel mio caso solo la getrichiesta funziona bene secondo la risposta di MindingData. Per altri tipi di richieste è necessario scrivere:

app.UseCors(corsPolicyBuilder =>
   corsPolicyBuilder.WithOrigins("http://localhost:3000")
  .AllowAnyMethod()
  .AllowAnyHeader()
);

Non dimenticare di aggiungere .AllowAnyHeader()


Concordo con Towhid sulla necessità di AllowAnyHeader (). Permette al server di ricevere la richiesta OPTIONS se nella richiesta HEADER manca qualcosa.
Rivon,

.AllowAnyHeader () l'ha fatto per me, ho avuto problemi con la risposta di verifica preliminare.
Takaz

11

Per espandere la risposta di user8266077 , ho scoperto che avevo ancora bisogno di fornire la risposta OPTIONS per le richieste di verifica preliminare in .NET Core 2.1-preview per il mio caso d'uso:

// https://stackoverflow.com/a/45844400
public class CorsMiddleware
{
  private readonly RequestDelegate _next;

  public CorsMiddleware(RequestDelegate next)
  {
    _next = next;
  }

  public async Task Invoke(HttpContext context)
  {
    context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
    context.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
    // Added "Accept-Encoding" to this list
    context.Response.Headers.Add("Access-Control-Allow-Headers", "Content-Type, X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Accept-Encoding, Content-Length, Content-MD5, Date, X-Api-Version, X-File-Name");
    context.Response.Headers.Add("Access-Control-Allow-Methods", "POST,GET,PUT,PATCH,DELETE,OPTIONS");
    // New Code Starts here
    if (context.Request.Method == "OPTIONS")
    {
      context.Response.StatusCode = (int)HttpStatusCode.OK;
      await context.Response.WriteAsync(string.Empty);
    }
    // New Code Ends here

    await _next(context);
  }
}

e quindi abilitato il middleware in questo modo in Startup.cs

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
  app.UseMiddleware(typeof(CorsMiddleware));
  // ... other middleware inclusion such as ErrorHandling, Caching, etc
  app.UseMvc();
}

1
Consiglio di aggiungere il middleware in questo modo:app.Use<CorsMiddleware>();
Albert221

È possibile sostituire quelle 2 linee: context.Response.StatusCode = (int) HttpStatusCode.OK; await context.Response.WriteAsync (string.Empty); con un semplice: ritorno;
Hayha,

1
Per espandere l'espansione della risposta di @ user8266077: attenzione che se la richiesta per qualche altro motivo fallisce, questo middleware genererà un'eccezione e le intestazioni non verranno impostate. Ciò significa che in frontend, sembrerà comunque un problema CORS anche se è qualcosa di totalmente diverso. Ho evitato questo rilevando eventuali eccezioni await _next(context)e impostando manualmente il codice di stato e la risposta se ciò accade. Ho anche dovuto aggiungere "autorizzazione" a Access-Control-Allow-Headers affinché la richiesta di verifica preliminare funzioni quando si effettuano richieste di reazione che richiedono l'autorizzazione.
Adam,

11
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {      
       app.UseCors(builder => builder
                .AllowAnyHeader()
                .AllowAnyMethod()
                .SetIsOriginAllowed((host) => true)
                .AllowCredentials()
            );
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors();
    }

.SetIsOriginAllowed ((host) => true) lo ha risolto per me.
JensB,

wow, quindi mi aspettavo che tutte le altre risposte funzionassero prima di questa piccola con solo 3 voti. ma ho provato meticolosamente ciascuno, ... per un capriccio sono andato per il tuo e, ha funzionato. grazie
roberto tomás,

Questo è quello che ha funzionato per me su .NET Core 3.1 per consentire praticamente qualsiasi cosa.
JustinHui,

10

Ho lottato con questo per DAYS.

Alla fine ho preso a lavorare spostando app.UseCors(CORS_POLICY);al TOP di Configure().

https://weblog.west-wind.com/posts/2016/sep/26/aspnet-core-and-cors-gotchas

Assicurati di dichiarare la funzionalità CORS prima di> MVC poiché le intestazioni devono essere applicate prima che MVC completi la richiesta.

<= Anche se la mia app non ha chiamato UseMVC(), lo spostamento UseCors()verso l'alto ha risolto il problema

Anche:

  • Microsoft.AspNetCore.Corsera un pacchetto NuGet richiesto in .Net Core 2 e versioni precedenti; ora fa automaticamente parte di Microsoft.AspNetCore in .Net Core 3 e versioni successive.
  • builder.AllowAnyOrigin()e le .AllowCredentials()opzioni CORS si escludono a vicenda in .Net Core 3 e versioni successive
  • La politica CORS sembra richiedere la chiamata angolare con il server https. Un URL http sembrava dare un errore CORS indipendentemente dalla configurazione CORS del server .Net Core. Ad esempio, http://localhost:52774/api/Contactsdarebbe un errore CORS; semplicemente cambiando l'URL in https://localhost:44333/api/Contactsfunzionato.

Nota aggiuntiva :

Nel mio caso, CORS non avrebbe funzionato fino a quando non mi sono spostato app.UseCors()sopra app.UseEndpoints(endpoints => endpoints.MapControllers()).


2
Questa dovrebbe essere la risposta se stai usando Net Core 3. Grazie per avermi salvato la vita!
Canada Wan

2
"Con il routing endpoint, il middleware CORS deve essere configurato per essere eseguito tra le chiamate a UseRouting e UseEndpoints. Una configurazione errata farà smettere di funzionare correttamente il middleware." qui docs.microsoft.com/en-us/aspnet/core/security/…
Mark Schultheiss

"Con il routing endpoint, il middleware CORS deve essere configurato per essere eseguito tra le chiamate a UseRouting e UseEndpoints. Una configurazione errata farà smettere di funzionare correttamente il middleware." qui docs.microsoft.com/en-us/aspnet/core/security/…
Mark Schultheiss

7

Nessuna delle procedure di cui sopra ha aiutato e ho quindi letto l' articolo che ha risolto il problema.

Di seguito è riportato il codice.

public void ConfigureServices(IServiceCollection services)
{
    // Add service and create Policy with options
    services.AddCors(options =>
    {
        options.AddPolicy("CorsPolicy",
            builder => builder.AllowAnyOrigin()
            .AllowAnyMethod()
            .AllowAnyHeader()
            .AllowCredentials() );
    });


    services.AddMvc(); 
}

e

public void Configure(IApplicationBuilder app)
{
    // ...

    // global policy - assign here or on each controller
    app.UseCors("CorsPolicy");

e in cima al mio metodo d'azione

[EnableCors("CorsPolicy")]

2
Questa è probabilmente una cattiva idea: non dovresti mescolare middleware ( app.UseCors()) con [EnableCors()]nella stessa applicazione. Dovresti usare l'uno o l'altro, ma non entrambi: docs.microsoft.com/en-us/aspnet/core/security/… :Use the [EnableCors] attribute or middleware, not both in the same app.
FoggyDay

4

prova ad aggiungere jQuery.support.cors = true;prima della chiamata Ajax

Potrebbe anche essere che i dati che invii all'API siano traballanti,

prova ad aggiungere la seguente funzione JSON

        var JSON = JSON || {};

    // implement JSON.stringify serialization
    JSON.stringify = JSON.stringify || function (obj) {

        var t = typeof (obj);
        if (t != "object" || obj === null) {

            // simple data type
            if (t == "string") obj = '"' + obj + '"';
            return String(obj);

        }
        else {

            // recurse array or object
            var n, v, json = [], arr = (obj && obj.constructor == Array);

            for (n in obj) {
                v = obj[n]; t = typeof (v);

                if (t == "string") v = '"' + v + '"';
                else if (t == "object" && v !== null) v = JSON.stringify(v);

                json.push((arr ? "" : '"' + n + '":') + String(v));
            }

            return (arr ? "[" : "{") + String(json) + (arr ? "]" : "}");
        }
    };

    // implement JSON.parse de-serialization
    JSON.parse = JSON.parse || function (str) {
        if (str === "") str = '""';
        eval("var p=" + str + ";");
        return p;
    };

quindi nei tuoi dati: oggetto modificalo in

    data: JSON.stringify({
        username: username,
        password: password
    }),

Grazie per l'aiuto. Sicuramente utilizzato una parte della risposta per capire la soluzione alla fine dopo aver combinato le risposte di tutti
killerrin

4

La soluzione più semplice è aggiungere

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

        app.UseCors(options => options.AllowAnyOrigin());

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

su Startup.cs.


3

Penso che se usi il tuo middleware CORS devi assicurarti che sia davvero una richiesta CORS controllando l' intestazione dell'origine .

 public class CorsMiddleware
{
    private readonly RequestDelegate _next;
    private readonly IMemoryCache _cache;
    private readonly ILogger<CorsMiddleware> _logger;

    public CorsMiddleware(RequestDelegate next, IMemoryCache cache, ILogger<CorsMiddleware> logger)
    {
        _next = next;
        _cache = cache;
        _logger = logger;
    }
    public async Task InvokeAsync(HttpContext context, IAdministrationApi adminApi)
    {
        if (context.Request.Headers.ContainsKey(CorsConstants.Origin) || context.Request.Headers.ContainsKey("origin"))
        {
            if (!context.Request.Headers.TryGetValue(CorsConstants.Origin, out var origin))
            {
                context.Request.Headers.TryGetValue("origin", out origin);
            }

            bool isAllowed;
            // Getting origin from DB to check with one from request and save it in cache 
            var result = _cache.GetOrCreateAsync(origin, async cacheEntry => await adminApi.DoesExistAsync(origin));
            isAllowed = result.Result.Result;

            if (isAllowed)
            {
                context.Response.Headers.Add(CorsConstants.AccessControlAllowOrigin, origin);
                context.Response.Headers.Add(
                    CorsConstants.AccessControlAllowHeaders,
                    $"{HeaderNames.Authorization}, {HeaderNames.ContentType}, {HeaderNames.AcceptLanguage}, {HeaderNames.Accept}");
                context.Response.Headers.Add(CorsConstants.AccessControlAllowMethods, "POST, GET, PUT, PATCH, DELETE, OPTIONS");

                if (context.Request.Method == "OPTIONS")
                {
                    _logger.LogInformation("CORS with origin {Origin} was handled successfully", origin);
                    context.Response.StatusCode = (int)HttpStatusCode.NoContent;
                    return;
                }

                await _next(context);
            }
            else
            {
                if (context.Request.Method == "OPTIONS")
                {
                    _logger.LogInformation("Preflight CORS request with origin {Origin} was declined", origin);
                    context.Response.StatusCode = (int)HttpStatusCode.NoContent;
                    return;
                }

                _logger.LogInformation("Simple CORS request with origin {Origin} was declined", origin);
                context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
                return;
            }
        }

        await _next(context);
    }

Grazie mille. Sono quasi impazzito, chiedendomi perché l' Access-Control-Allow-Originintestazione non è stata emessa dal server. In realtà ho inviato richieste tramite Postman senza l' Originintestazione. Questo mi ha salvato la giornata! (O almeno la mia mattinata;))
Paul Kertscher l'

2

Sulla base del tuo commento nella risposta di MindingData, non ha nulla a che fare con il tuo CORS, funziona bene.

L'azione del tuo controller sta restituendo dati errati. HttpCode 415 significa "Tipo di supporto non supportato". Ciò accade quando si passa il formato errato al controller (ovvero XML a un controller che accetta solo json) o quando si restituisce un tipo errato (restituire Xml in un controller che viene dichiarato restituire solo xml).

Per un seguito, controlla l'esistenza [Produces("...")]dell'attributo sulla tua azione


Grazie per l'aiuto. Ho provato una nuova soluzione e ho giocato con JSON inviato e ha funzionato dopo che l'ho stretto e fatto funzionare
killerrin

2

Per me, non aveva nulla a che fare con il codice che stavo usando. Per Azure abbiamo dovuto accedere alle impostazioni del servizio app, nel menu laterale la voce "CORS". Lì ho dovuto aggiungere il dominio da cui stavo richiedendo materiale. Una volta che l'ho avuto dentro, tutto era magico.


2

In launchSettings.json, sotto iisSettings, imposta anonymousAuthentication su true:

"iisSettings": {
    "windowsAuthentication": true,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:4200/",
      "sslPort": 0
    }
  }

Quindi, in Startup.cs, in ConfigureServices, prima di services.AddMvc, aggiungi:

services.AddCors(options => options.AddPolicy("ApiCorsPolicy", builder =>
{
    builder
        .AllowAnyOrigin()
        .WithHeaders(HeaderNames.AccessControlAllowHeaders, "Content-Type")
        .AllowAnyMethod()
        .AllowCredentials();
}));

e quindi, nel metodo di configurazione, prima di app.UseMvc () aggiungere:

app.UseCors("ApiCorsPolicy");

Questo è stato per me, inizialmente ho impostato il mio progetto per l'autenticazione di Windows, ma poi ho dovuto cambiarlo in anonimo, avevo CORS correttamente configurato ma questa impostazione in launchSettings.json era il colpevole, grazie per aver pubblicato questo !.
HaRoLD,

2

Sto usando .Net CORE 3.1 e ho passato anni a sbattere la testa contro un muro con questo quando mi sono reso conto che il mio codice ha iniziato effettivamente a funzionare ma il mio ambiente di debug era rotto, quindi ecco 2 suggerimenti se stai cercando di risolvere il problema:

  1. Se stai tentando di registrare le intestazioni di risposta utilizzando il middleware ASP.NET, l'intestazione "Access-Control-Allow-Origin" non verrà mai visualizzata anche se è presente. Non so come, ma sembra essere aggiunto al di fuori della pipeline (alla fine ho dovuto usare WireShark per vederlo).

  2. .NET CORE non invierà "Access-Control-Allow-Origin" nella risposta a meno che tu non abbia un'intestazione "Origin" nella tua richiesta. Postman non lo imposterà automaticamente, quindi dovrai aggiungerlo tu stesso.


2

Nel mio caso ho risolto con UseCors prima di UserRouting ..


Mi sono imbattuto in qualcosa di simile quando ho aggiornato da dotnet core 2.2 a 3.1. Ho dovuto spostare app.UseCors () sopra app.UseRouting (). Questa risposta mi ha indicato la giusta direzione.
Brandonm,

1

.NET Core 3.1

Ha funzionato per me e come dicono i dottori per farlo:

nella classe di avvio:

readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins"; 

Nel metodo ConfigureServices ():

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

Nel metodo Configure ():

    app.UseCors(MyAllowSpecificOrigins);  

https://docs.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-3.1


0

Ho ottenuto la risposta di MindingData sopra per funzionare, ma ho dovuto usare Microsoft.AspNet.Cors invece di Microsoft.AspNetCore.Cors. Sto usando il progetto API Web Application .NetCore in Visual Studio 2019


2
NOTA: non è necessario utilizzare Microsoft.AspNet.Cors in un'applicazione Cor ASP.Net. Se utilizzi .Net Core 3.0 o versioni successive, non è necessario importare alcun pacchetto NuGet per CORS. Se utilizzi .Net Core 2.3 o versioni precedenti, devi disporre della versione appropriata di Microsoft.AspNet.Cors di NuGet.
FoggyDay

0

Il

Microsoft.AspNetCore.Cors

ti consentirà di eseguire CORS con funzionalità integrate, ma non gestisce la richiesta OPTIONS. La soluzione alternativa migliore finora è la creazione di un nuovo middleware come suggerito in un post precedente. Controlla la risposta contrassegnata come corretta nel seguente post:

Abilitare l'intestazione OPTIONS per CORS sull'API Web .NET Core


0

Modo semplice e facile per farlo.

  1. Installa pacchetto

Install-Package Microsoft.AspNetCore.Cors

  1. Inserisci questo codice nel file startup.cs

app.UseCors(options => options.AllowAnyOrigin());


0

Ecco il mio codice:)

  app.Use((ctx, next) =>
        {
            ctx.Response.Headers.Add("Access-Control-Allow-Origin", ctx.Request.Headers["Origin"]);
            ctx.Response.Headers.Add("Access-Control-Allow-Methods", "*");
            ctx.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
            ctx.Response.Headers.Add("Access-Control-Allow-Headers", "AccessToken,Content-Type");
            ctx.Response.Headers.Add("Access-Control-Expose-Headers", "*");
            if (ctx.Request.Method.ToLower() == "options")
            {
                ctx.Response.StatusCode = 204;

                return Task.CompletedTask;
            }
            return next();
        });

0

Ecco come l'ho fatto.

Vedo che in alcune risposte stanno impostando app.UserCors("xxxPloicy")e inserendo [EnableCors("xxxPloicy")]controller. Non è necessario fare entrambe le cose.

Ecco i passaggi.

In Startup.cs all'interno di ConfigureServices aggiungi il seguente codice.

    services.AddCors(c=>c.AddPolicy("xxxPolicy",builder => {
        builder.AllowAnyOrigin()
        .AllowAnyMethod()
        .AllowAnyHeader();
    }));

Se si desidera applicare in tutto il progetto, aggiungere il seguente codice nel metodo Configura in Startup.cs

app.UseCors("xxxPolicy");

O

Se si desidera aggiungerlo ai controller specifici, aggiungere il codice cors abilita come mostrato di seguito.

[EnableCors("xxxPolicy")]
[Route("api/[controller]")]
[ApiController]
public class TutorialController : ControllerBase {}

Per maggiori informazioni: vedi questo


0

Utilizzare un attributo di azione / controller personalizzato per impostare le intestazioni CORS.

Esempio:

public class AllowMyRequestsAttribute : ControllerAttribute, IActionFilter
{
    public void OnActionExecuted(ActionExecutedContext context)
    {
        // check origin
        var origin = context.HttpContext.Request.Headers["origin"].FirstOrDefault();
        if (origin == someValidOrigin)
        {
            context.HttpContext.Response.Headers.Add("Access-Control-Allow-Origin", origin);
            context.HttpContext.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
            context.HttpContext.Response.Headers.Add("Access-Control-Allow-Headers", "*");
            context.HttpContext.Response.Headers.Add("Access-Control-Allow-Methods", "*");
            // Add whatever CORS Headers you need.
        }
    }

    public void OnActionExecuting(ActionExecutingContext context)
    {
        // empty
    }
}

Quindi sul controller API Web / Azione:

[ApiController]
[AllowMyRequests]
public class MyController : ApiController
{
    [HttpGet]
    public ActionResult<string> Get()
    {
        return "Hello World";
    }
}

0

Solo per aggiungere per rispondere qui, se si sta utilizzando app.UseHttpsRedirection()e non si sta colpendo la porta SSL, prendere in considerazione di commentare questo.


0

Stavo usando il webassembly blazor come client e asp.net web api core come backend e avevo anche problemi con il cors.

Ho trovato una soluzione con questo codice:

Il mio ASP.Net core web api Startup.cs ConfiguraServizi e configura le prime righe è simile al seguente:

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

 //other code below...
}

e il mio metodo Configure:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseCors(
        options =>   options.WithOrigins("http://example.com").AllowAnyMethod().AllowAnyHeader()
            );
 //other code below...
}

cambiare http://example.comcon il dominio client o l'indirizzo IP


-1
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
                .AddJsonOptions(options => {
                    var resolver = options.SerializerSettings.ContractResolver;
                    if (resolver != null)
                        (resolver as DefaultContractResolver).NamingStrategy = null;
                });

            services.AddDbContext<PaymentDetailContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DevConnection"))); //Dependency Injection
            // options => options.UseSqlServer() Lamda Expression

            services.AddCors(options =>
            {
                options.AddPolicy(MyAllowSpecificOrigins,
                    builder =>
                    {
                        builder.WithOrigins("http://localhost:4200").AllowAnyHeader()
                                .AllowAnyMethod(); ;
                    });
            });

Modifica la tua risposta per includere e spiegazione del tuo codice e in che modo differisce dalle altre risposte. Questo renderà il tuo post più utile e più probabile che venga messo in evidenza :)
Das_Geek,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.