So aktivieren Sie CORS in ASP.net Core WebAPI

188

Was ich versuche zu tun

Ich habe eine Backend-ASP.Net Core-Web-API, die auf einem Azure Free Plan gehostet wird (Quellcode: https://github.com/killerrin/Portfolio-Backend ).

Ich habe auch eine Client-Website, auf der diese API verwendet werden soll. Die Clientanwendung wird nicht auf Azure gehostet, sondern auf Github Pages oder einem anderen Webhostingdienst, auf den ich Zugriff habe. Aus diesem Grund werden die Domainnamen nicht ausgerichtet.

In diesem Zusammenhang muss ich CORS auf der Web-API-Seite aktivieren. Ich habe jedoch seit einigen Stunden so gut wie alles ausprobiert und es weigert sich zu funktionieren.

Wie ich das Client-Setup habe Es ist nur ein einfacher Client, der in React.js geschrieben ist. Ich rufe die APIs über AJAX in Jquery auf. Die React-Site funktioniert, also weiß ich, dass es das nicht ist. Der Jquery-API-Aufruf funktioniert wie in Versuch 1 bestätigt. So tätige ich die Aufrufe

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

Was ich versucht habe


Versuch 1 - Der "richtige" Weg

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

Ich habe dieses Tutorial auf der Microsoft-Website bis zu einem T befolgt und alle drei Optionen ausprobiert, um es global in Startup.cs zu aktivieren, es auf jedem Controller einzurichten und es bei jeder Aktion zu versuchen.

Nach dieser Methode funktioniert die domänenübergreifende Funktion, jedoch nur für eine einzelne Aktion auf einem einzelnen Controller (POST an den AccountController). Für alles andere Microsoft.AspNetCore.Corsweigert sich die Middleware, die Header zu setzen.

Ich habe Microsoft.AspNetCore.Corsüber NUGET installiert und die Version ist1.1.2

Hier ist, wie ich es in Startup.cs eingerichtet habe

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

        ...
        ...
        ...
    }

Wie Sie sehen können, mache ich alles wie gesagt. Ich füge beide Male Cors vor MVC hinzu, und als das nicht funktionierte, versuchte ich, [EnableCors("MyPolicy")]jeden Controller so einzuschalten

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

Versuch 2 - Brute Forcing it

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

Nachdem ich den vorherigen Versuch mehrere Stunden lang ausprobiert hatte, dachte ich, ich würde versuchen, ihn zu erzwingen, indem ich versuchte, die Header manuell festzulegen, sodass sie bei jeder Antwort ausgeführt werden mussten. Ich habe dies nach diesem Tutorial getan, wie man jeder Antwort manuell Header hinzufügt.

Dies sind die Header, die ich hinzugefügt habe

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

Dies sind andere Header, die ich ausprobiert habe und die fehlgeschlagen sind

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

Bei dieser Methode werden die Cross Site-Header ordnungsgemäß angewendet und in meiner Entwicklerkonsole und in Postman angezeigt. Das Problem ist jedoch, dass Access-Control-Allow-Originder Webbrowser , während er die Prüfung besteht, einen zischenden Anfall auf (glaube ich) Access-Control-Allow-HeadersAussage macht415 (Unsupported Media Type)

Die Brute-Force-Methode funktioniert also auch nicht


Schließlich

Hat jemand dies zum Laufen gebracht und könnte helfen oder mich einfach in die richtige Richtung weisen?


BEARBEITEN

Damit die API-Aufrufe ausgeführt werden konnten, musste ich JQuery nicht mehr verwenden und zu einem Pure Javascript- XMLHttpRequestFormat wechseln .

Versuch 1

Ich schaffte es das zu bekommen , Microsoft.AspNetCore.Corsum die Arbeit von MindingData Antwort folgen, es sei denn innerhalb der ConfigureMethode der Umsetzung app.UseCorsvor app.UseMvc.

Darüber hinaus begann das Mischen mit der Javascript-API-Lösung options.AllowAnyOrigin()für die Platzhalterunterstützung ebenfalls zu funktionieren.

Versuch 2

Ich habe es also geschafft, Versuch 2 (Brute Forcing It) zum Laufen zu bringen ... mit der einzigen Ausnahme, dass der Platzhalter für Access-Control-Allow-Originnicht funktioniert, und als solche muss ich die Domänen, die Zugriff darauf haben, manuell festlegen.

Es ist offensichtlich nicht ideal, da ich nur möchte, dass dieses WebAPI für alle zugänglich ist, aber es funktioniert zumindest für mich auf einer separaten Site, was bedeutet, dass es ein Anfang ist

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"));
Killerrin
quelle
2
415 (Unsupported Media Type)Setzen Sie für Ihr Problem einen Content-TypeAnforderungsheader auf application/json.
Technetium
5
Vielen Dank, dass Sie sich die Zeit genommen haben, eine solche beschreibende Frage zu schreiben.
user1007074
1
Wenn Sie mit Postman testen, stellen Sie sicher, dass Sie Origin für den Anforderungsheader auf * oder etwas anderes setzen. Dann sollte Versuch 1 funktionieren. Ohne diesen Header wird Access-Control-Allow-Origin nicht im Antwortheader zurückgegeben.
Tala9999

Antworten:

236

Da Sie eine sehr einfache CORS-Richtlinie haben (Alle Anforderungen von der XXX-Domäne zulassen), müssen Sie diese nicht so kompliziert gestalten. Versuchen Sie zunächst Folgendes (Eine sehr grundlegende Implementierung von CORS).

Wenn Sie dies noch nicht getan haben, installieren Sie das CORS-Nuget-Paket.

Install-Package Microsoft.AspNetCore.Cors

Fügen Sie in der ConfigureServices-Methode Ihrer startup.cs die CORS-Services hinzu.

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

Fügen Sie dann in Ihrer Configure-Methode Ihrer startup.cs Folgendes hinzu:

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

Jetzt probieren Sie es aus. Richtlinien gelten für den Fall, dass Sie unterschiedliche Richtlinien für unterschiedliche Aktionen wünschen (z. B. unterschiedliche Hosts oder unterschiedliche Header). Für Ihr einfaches Beispiel brauchen Sie es wirklich nicht. Beginnen Sie mit diesem einfachen Beispiel und optimieren Sie es von dort aus nach Bedarf.

Lesen Sie weiter: http://dotnetcoretutorials.com/2017/01/03/enabling-cors-asp-net-core/

MindingData
quelle
3
XMLHttpRequest kann andrewgodfroyportfolioapi.azurewebsites.net/api/Authentication nicht laden . Die Antwort auf die Preflight-Anforderung besteht die Zugriffssteuerungsprüfung nicht: In der angeforderten Ressource ist kein Header 'Access-Control-Allow-Origin' vorhanden. Origin ' localhost: 3000 ' ist daher nicht zugänglich. Die Antwort hatte HTTP-Statuscode 415.
Killerrin
7
Dies wird wahrscheinlich nicht funktionieren, wenn Sie sich app.UseCors NACH `` app.UseMvc () ` registrieren . Middlewares werden in der Reihenfolge ausgeführt, in der sie registriert sind
Tseng
24
Die Verwendung von app.UseCors vor app.UseMvc in der Configure-Methode scheint zu funktionieren. Aus irgendeinem Grund scheint die Reihenfolge von Bedeutung zu sein.
MrClan
1
Für mich ist das größte Problem von CORS in 2.0, dass es nicht sagt, was falsch ist, sondern nur stillschweigend keine CORS-Header setzt. Hinweis : Denken Sie daran, alle erforderlichen Header zur Richtlinie hinzuzufügen, da dies sonst fehlschlägt (ich hatte den Inhaltstyp). Auch seltsam für mich, dass die CORS-Middleware die Anforderungsverarbeitung nicht bremst, sondern nur in Protokollen darüber informiert, dass der Ursprung nicht zulässig ist und .. die Anforderung weiterleitet (Middleware-Reihenfolge war korrekt).
Andrii M4n0w4R
2
Ich musste aktivieren options.DisableHttpsRequirement();, damit dies funktioniert. Es scheint, dass mit https cors Einstellungen nicht zutrafen.
Michael Brown
206
  • Fügen Sie in ConfigureServices services.AddCors(); BEFORE services.AddMvc () hinzu.
  • Fügen Sie UseCors in Configure hinzu

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

Hauptpunkt ist das Hinzufügen app.UseCorsvor app.UseMvc().

Stellen Sie sicher, dass Sie die CORS-Funktionalität vor MVC deklarieren, damit die Middleware ausgelöst wird, bevor die MVC-Pipeline die Kontrolle erhält und die Anforderung beendet.

Nachdem die oben beschriebene Methode funktioniert hat, können Sie sie ändern, indem Sie einen bestimmten ORIGIN konfigurieren, um API-Aufrufe zu akzeptieren und zu vermeiden, dass Ihre API für jedermann offen bleibt

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

Weisen Sie CORS in der Konfigurationsmethode an, die gerade erstellte Richtlinie zu verwenden:

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

Ich habe gerade diesen kompakten Artikel zu diesem Thema gefunden - https://dzone.com/articles/cors-in-net-core-net-core-security-part-vi

Ji Ra
quelle
1
Das funktioniert bei mir. codeproject.com/Articles/1150023/…
hubert17
17
Dies sollte wirklich mehr positive Stimmen als guten "Ausgangspunkt" bekommen. Nach meiner Erfahrung in über 25 Jahren Codierung ist es immer schön zu wissen, wie man die Schleusen öffnet, um sicherzustellen, dass sie tatsächlich "funktionieren", und dann die Dinge nach Bedarf zu schließen / zu sichern.
Indy-Jones
4
Genau dies zu erwähnen, im Gegensatz zu Configure()der Reihenfolge ist nicht wirklich wichtig , hier inConfigureServices()
B12Toaster
Ich habe den Link im Further Reader verwendet und diese Schritte haben diesen Fehler behoben. Ich war mir nicht sicher, wo diese Änderungen platziert werden sollten (ich dachte, die API). Der Link bestätigte, dass sie in der API platziert werden sollten. Danke für die Hilfe. Ich habe meine Räder mit diesem Fehler total durchgedreht.
Richard
Dies funktioniert mit Asp.Net Core 2.1 und vor allem mit localhost
Michal Frystacky
28

Ich habe meine eigene Middleware-Klasse erstellt, die für mich funktioniert hat. Ich denke, mit der .net-Core-Middleware-Klasse stimmt etwas nicht

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

und verwendet es auf diese Weise in der startup.cs

app.UseCorsMiddleware();
user8266077
quelle
Sehr elegante Art, Access-Control-Allow-Origin auszuführen.
Artur Poniedziałek
Dies funktioniert auf WebAPI und MVC und hat keine Abhängigkeiten. Vielen Dank!
Joe
Ich war auch skeptisch, aber es hat bei mir funktioniert. Ich habe im Grunde jede andere Methode ausprobiert, um dies zu erreichen, die ich im Internet finden konnte, aber egal, was der Server nicht mit den Zugriffsköpfen antworten würde. Das hat super geklappt. Ich verwende Aspnetcore 2.1.
Jordanien
Sie sollten cors-Header nur zurückgeben, wenn der Client auf Anfrage den Header "Origin" sendet. In original CospMiddleware sieht es so aus:if (!context.Request.Headers.ContainsKey(CorsConstants.Origin)) return this._next(context);
Andrew Prigorshnev
Vielleicht "stimmt etwas mit der .net Core Middleware-Klasse nicht", weil Sie beim Testen mit Curl oder ähnlichem einfach nicht den Header "Origin" hinzufügen. Browser fügen diesen Header automatisch hinzu, wenn Sie eine Anfrage in js Code stellen.
Andrew Prigorshnev
16

In meinem Fall getfunktioniert nur die Anfrage gemäß der Antwort von MindingData. Für andere Arten von Anfragen müssen Sie schreiben:

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

Vergiss nicht hinzuzufügen .AllowAnyHeader()

Towhid
quelle
Stimmen Sie Towhid zu, dass AllowAnyHeader () benötigt wird. Der Server erhält die OPTIONS-Anfrage, wenn in der HEADER-Anfrage etwas fehlt.
Rivon
Der .AllowAnyHeader () hat es für mich getan, ich hatte Probleme mit der Preflight-Antwort.
Takaz
11

Um auf erweitern user8266077 ‚s Antwort , fand ich , dass ich brauchte noch Versorgung OPTIONS Antwort für Preflight - Anfragen in .NET Core - 2.1-Vorschau für meinen Anwendungsfall:

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

und dann die Middleware wie folgt in Startup.cs aktiviert

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
  app.UseMiddleware(typeof(CorsMiddleware));
  // ... other middleware inclusion such as ErrorHandling, Caching, etc
  app.UseMvc();
}
ckr
quelle
1
Ich empfehle, Middleware auf diese Weise hinzuzufügen:app.Use<CorsMiddleware>();
Albert221
Sie können diese 2 Zeichen ersetzen: context.Response.StatusCode = (int) HttpStatusCode.OK; warte auf context.Response.WriteAsync (string.Empty); mit einem einfachen: return;
Hayha
1
So erweitern Sie Ihre Erweiterung der Antwort von @ user8266077: Beachten Sie, dass diese Middleware eine Ausnahme auslöst und die Header nicht festgelegt werden, wenn die Anforderung aus einem anderen Grund fehlschlägt. Das bedeutet, dass es im Frontend immer noch wie ein CORS-Problem aussieht, obwohl es etwas völlig anderes ist. Ich habe dies umgangen, indem ich Ausnahmen abgefangen await _next(context)und den Statuscode und die Antwort manuell festgelegt habe, wenn dies passiert. Ich musste auch "Autorisierung" zu Access-Control-Allow-Headern hinzufügen, damit die Preflight-Anforderung funktioniert, wenn Anforderungen von React gestellt werden, für die eine Autorisierung erforderlich ist.
Adam
10
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {      
       app.UseCors(builder => builder
                .AllowAnyHeader()
                .AllowAnyMethod()
                .SetIsOriginAllowed((host) => true)
                .AllowCredentials()
            );
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors();
    }
Mo D Genesis
quelle
.SetIsOriginAllowed ((host) => true) hat es für mich gelöst.
JensB
wow, also habe ich voll und ganz damit gerechnet, dass eine der anderen Antworten vor diesem Kleinen mit nur 3 Stimmen funktioniert. aber ich habe jeden akribisch ausprobiert, ... aus einer Laune heraus habe ich mich für deine entschieden und es hat funktioniert. danke
roberto tomás
9

Ich hatte seit Tagen damit zu kämpfen.

Ich habe es endlich an die Arbeit , indem app.UseCors(CORS_POLICY);zum TOP von Configure().

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

Stellen Sie sicher, dass Sie die CORS-Funktionalität vor> MVC deklarieren, da die Header angewendet werden müssen, bevor MVC die Anforderung abschließt.

<= Obwohl meine App nicht angerufen hat UseMVC(), wurde UseCors()das Problem durch Verschieben nach oben behoben

Ebenfalls:

  • Microsoft.AspNetCore.Corswar früher ein erforderliches NuGet-Paket in .Net Core 2 und niedriger; Es ist jetzt automatisch Teil von Microsoft.AspNetCore in .Net Core 3 und höher.
  • builder.AllowAnyOrigin()und .AllowCredentials()CORS-Optionen schließen sich jetzt in .Net Core 3 und höher gegenseitig aus
  • Die CORS-Richtlinie scheint zu erfordern, dass Angular den Server mit anruft https. Eine http-URL schien unabhängig von der CORS-Konfiguration des .Net Core-Servers einen CORS-Fehler zu verursachen. http://localhost:52774/api/ContactsWürde zum Beispiel einen CORS-Fehler geben; Ändern Sie einfach die URL auf https://localhost:44333/api/Contactsfunktioniert.

Zusätzlicher Hinweis :

In meinem Fall würde CORS nicht funktionieren, bis ich nach app.UseCors()oben gezogen bin app.UseEndpoints(endpoints => endpoints.MapControllers()).

Nebliger Tag
quelle
2
Dies sollte die Antwort sein, wenn Sie Net Core 3 verwenden. Vielen Dank, dass Sie mein Leben gerettet haben!
Kanada Wan
2
"Beim Endpoint-Routing muss die CORS-Middleware so konfiguriert sein, dass sie zwischen den Aufrufen von UseRouting und UseEndpoints ausgeführt wird. Eine falsche Konfiguration führt dazu, dass die Middleware nicht mehr ordnungsgemäß funktioniert." hier docs.microsoft.com/en-us/aspnet/core/security/…
Mark Schultheiss
"Beim Endpoint-Routing muss die CORS-Middleware so konfiguriert sein, dass sie zwischen den Aufrufen von UseRouting und UseEndpoints ausgeführt wird. Eine falsche Konfiguration führt dazu, dass die Middleware nicht mehr ordnungsgemäß funktioniert." hier docs.microsoft.com/en-us/aspnet/core/security/…
Mark Schultheiss
7

Keines der oben genannten Verfahren hat geholfen und ich habe dann einen Artikel gelesen, der das Problem gelöst hat.

Unten ist der Code.

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

und

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

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

und ganz oben auf meiner Aktionsmethode

[EnableCors("CorsPolicy")]
Sainath
quelle
2
Dies ist wahrscheinlich eine schlechte Idee: Sie sollten Middleware ( app.UseCors()) nicht [EnableCors()]in derselben Anwendung mischen . Sie sollten das eine oder das andere verwenden - aber nicht beide: docs.microsoft.com/en-us/aspnet/core/security/… :Use the [EnableCors] attribute or middleware, not both in the same app.
FoggyDay
4

Versuchen Sie, jQuery.support.cors = true;vor dem Ajax-Aufruf hinzuzufügen

Es kann auch sein, dass die Daten, die Sie an die API senden, wackelig sind.

Versuchen Sie, die folgende JSON-Funktion hinzuzufügen

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

dann in Ihren Daten: Objekt ändern Sie es in

    data: JSON.stringify({
        username: username,
        password: password
    }),
Riaan Saayman
quelle
Danke für Ihre Hilfe. Auf jeden Fall einen Teil der Antwort verwendet, um die Lösung am Ende herauszufinden, nachdem alle Antworten kombiniert wurden
Killerrin
4

Einfachste Lösung ist hinzufügen

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

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

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

zu Startup.cs.

Amilamad
quelle
3

Ich denke, wenn Sie Ihre eigene CORS- Middleware verwenden, müssen Sie sicherstellen, dass es sich wirklich um eine CORS- Anforderung handelt, indem Sie den Ursprungsheader überprüfen .

 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);
    }
Riddik
quelle
Vielen Dank. Ich wurde fast verrückt und fragte mich, warum der Access-Control-Allow-OriginHeader nicht vom Server ausgegeben wurde. Eigentlich habe ich Anfragen per Postbote ohne OriginHeader gesendet . Das hat mir den Tag gerettet! (Oder zumindest mein Vormittag;))
Paul Kertscher
2

Basierend auf Ihrem Kommentar in der Antwort von MindingData hat dies nichts mit Ihrem CORS zu tun. Es funktioniert einwandfrei.

Ihre Controller-Aktion gibt die falschen Daten zurück. HttpCode 415 bedeutet "Nicht unterstützter Medientyp". Dies geschieht, wenn Sie entweder das falsche Format an den Controller übergeben (dh XML an einen Controller, der nur JSON akzeptiert) oder wenn Sie einen falschen Typ zurückgeben (XML in einem Controller zurückgeben, der nur XML zurückgibt).

Für später überprüfen Sie das Vorhandensein eines [Produces("...")]Attributs in Ihrer Aktion

Tseng
quelle
Danke für Ihre Hilfe. Versuchte eine neue Lösung und spielte mit dem Versenden von Json und es funktionierte, nachdem ich es stringifiziert und zum
Laufen gebracht hatte
2

Für mich hatte das nichts mit dem Code zu tun, den ich verwendete. Für Azure mussten wir in die Einstellungen des App Service gehen, im Seitenmenü den Eintrag "CORS". Dort musste ich die Domain hinzufügen, von der ich Sachen angefordert hatte. Sobald ich das hatte, war alles magisch.

kjbetz
quelle
2

Setzen Sie in launchSettings.json unter iisSettings die anonyme Authentifizierung auf true:

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

Fügen Sie dann in Startup.cs unter ConfigureServices vor services.AddMvc Folgendes hinzu:

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

und dann in der Methode configure vor app.UseMvc () Folgendes hinzufügen:

app.UseCors("ApiCorsPolicy");
Adrian
quelle
Dies hat es für mich getan. Ich habe mein Projekt ursprünglich für die Windows-Authentifizierung eingerichtet, musste es dann aber in anonym ändern. Ich hatte CORS korrekt konfiguriert, aber diese Einstellung in launchSettings.json war der Schuldige. Vielen Dank, dass Sie dies gepostet haben.
HaRoLD
2

Ich verwende .Net CORE 3.1 und habe lange Zeit damit verbracht, meinen Kopf gegen eine Wand zu schlagen, als mir klar wurde, dass mein Code tatsächlich funktioniert, meine Debugging-Umgebung jedoch fehlerhaft war. Hier sind also zwei Hinweise, wenn Sie versuchen, das Problem zu beheben Problem:

  1. Wenn Sie versuchen, Antwortheader mit ASP.NET-Middleware zu protokollieren, wird der Header "Access-Control-Allow-Origin" niemals angezeigt, selbst wenn er vorhanden ist. Ich weiß nicht wie, aber es scheint außerhalb der Pipeline hinzugefügt zu werden (am Ende musste ich Wireshark verwenden, um es zu sehen).

  2. .NET CORE sendet in der Antwort nicht "Access-Control-Allow-Origin", es sei denn, Ihre Anfrage enthält einen "Origin" -Header. Postman stellt dies nicht automatisch ein, daher müssen Sie es selbst hinzufügen.

Andy
quelle
1

.NET Core 3.1

Arbeitete für mich und wie die Dokumente sagen, um es zu tun:

in der Startup-Klasse:

readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins"; 

In der ConfigureServices () -Methode:

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

In der Configure () -Methode:

    app.UseCors(MyAllowSpecificOrigins);  

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

Andrew
quelle
1

In meinem Fall habe ich vor dem UserRouting mit UseCors behoben.

René Bizelli de Oliveira
quelle
0

Ich habe die Antwort von MindingData oben zum Laufen gebracht, musste aber Microsoft.AspNet.Cors anstelle von Microsoft.AspNetCore.Cors verwenden. Ich verwende das .NetCore-Webanwendungs-API-Projekt in Visual Studio 2019

Carl
quelle
2
HINWEIS: Sie sollten Microsoft.AspNet.Cors nicht in einer ASP.Net Cor-Anwendung verwenden. Wenn Sie mit .Net Core 3.0 oder höher arbeiten, müssen Sie für CORS überhaupt kein NuGet-Paket importieren. Wenn Sie mit .Net Core 2.3 oder niedriger arbeiten, benötigen Sie die entsprechende Version von Microsoft.AspNet.Cors von NuGet.
FoggyDay
0

Das

Microsoft.AspNetCore.Cors

Mit dieser Funktion können Sie CORS mit integrierten Funktionen ausführen, OPTIONS-Anforderungen werden jedoch nicht verarbeitet. Die bisher beste Problemumgehung ist das Erstellen einer neuen Middleware, wie in einem vorherigen Beitrag vorgeschlagen. Überprüfen Sie die Antwort, die im folgenden Beitrag als richtig markiert ist:

Aktivieren Sie den OPTIONS-Header für CORS in der .NET Core-Web-API

Bonomi
quelle
0

Einfache und einfache Möglichkeit, dies zu tun.

  1. Installationspaket

Install-Package Microsoft.AspNetCore.Cors

  1. Fügen Sie den folgenden Code in die Datei startup.cs ein

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

Pintu Sharma
quelle
0

Hier ist mein Code :)

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

Hier ist, wie ich das gemacht habe.

Ich sehe, dass in einigen Antworten sie setzen app.UserCors("xxxPloicy")und setzen[EnableCors("xxxPloicy")] in Controllern. Sie müssen nicht beides tun.

Hier sind die Schritte.

Fügen Sie in Startup.cs in den ConfigureServices den folgenden Code hinzu.

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

Wenn Sie das gesamte Projekt anwenden möchten, fügen Sie den folgenden Code unter Configure method in Startup.cs hinzu

app.UseCors("xxxPolicy");

Oder

Wenn Sie es den spezifischen Controllern hinzufügen möchten, fügen Sie den Aktivierungscode wie unten gezeigt hinzu.

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

Weitere Informationen finden Sie hier

Arshath Shameer
quelle
0

Verwenden Sie ein benutzerdefiniertes Aktions- / Controller-Attribut, um die CORS-Header festzulegen.

Beispiel:

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

Dann auf dem Web API Controller / Aktion:

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

Nur um hier eine Antwort hinzuzufügen, wenn Sie verwenden app.UseHttpsRedirection()und keinen SSL-Port erreichen, sollten Sie dies auskommentieren.

Raj
quelle
0

Ich habe Blazor Webassembly als Client und Asp.net Web API Core als Backend verwendet und hatte auch Cors Probleme.

Ich habe mit diesem Code eine Lösung gefunden:

Die ersten Zeilen meiner ASP.Net-Kern-Web-API Startup.cs ConfigureServices und Configure-Methoden sehen folgendermaßen aus:

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

 //other code below...
}

und meine Configure-Methode:

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

Ändern Sie http://example.commit Ihrer Client-Domain oder IP-Adresse

Zviadi
quelle
-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(); ;
                    });
            });
Albin CS
quelle
Bitte bearbeiten Sie Ihre Antwort, um Ihren Code aufzunehmen und zu erläutern und wie er sich von den anderen Antworten unterscheidet. Dies macht Ihren Beitrag nützlicher und wahrscheinlicher, dass er positiv bewertet wird :)
Das_Geek