Versuch, CORS mit Authentifizierung einzurichten. Ich habe eine Web-API-Site unter http: // localhost: 61000 und eine konsumierende Webanwendung unter http: // localhost: 62000. In der Web-API Startup.cs habe ich:

 public void ConfigureServices(IServiceCollection services)
 {
        services.AddCors(o => o.AddPolicy("MyPolicy", corsBuilder =>
        {
            corsBuilder.WithOrigins("http://localhost:62000")
                .AllowAnyMethod()
                .AllowAnyHeader()
                .AllowCredentials();
        }));
        IMvcBuilder builder = services.AddMvc();
        // ...
}

// ...

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
        app.UseCors("MyPolicy");
        app.UseDeveloperExceptionPage();
        app.UseDefaultFiles();
        app.UseStaticFiles();
        app.UseMvc();
}

Die gesamte Dokumentation scheint darauf hinzudeuten, dass dies alles sein sollte, was ich brauche. Im Javascript meiner App rufe ich auf:

    $.ajax({
        type: 'POST',
        url: "http://localhost:61000/config/api/v1/MyStuff",
        data: matchForm.serialize(),
        crossDomain: true,
        xhrFields: { withCredentials: true },
        success: function (data) {
            alert(data);
        }
    });

Und ich bekomme in Chrome: Failed to load http://localhost:61000/config/api/v1/MyStuff: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:62000' is therefore not allowed access.

... und in Firefox: Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:61000/config/api/v1/MyStuff. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).

Was vermisse ich? Das sollte alles sein, was ich brauche, um CORS zu aktivieren, dachte ich, aber es fehlt eindeutig noch etwas.

8
Patrick Szalapski 18 Apr. 2018 im 15:47

4 Antworten

Beste Antwort

Für ASP.NET Core 2.1 und früher:

Es scheint, dass in meinem Code ein Fehler aufgetreten ist, aber ich habe den obskuren Fehler festgestellt, anstatt eine von ASP.NET generierte Fehlerseite zu erhalten. Es stellt sich heraus, dass die CORS-Header zwar zuerst richtig angewendet werden, aber dann alle von ASP.NET-Middleware generierten Fehler entfernt werden. Siehe auch https://github.com/aspnet/Home/issues/2378.

Ich habe diesen Link benutzt, um diese Klasse herauszufinden

using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;

namespace MySite.Web.Middleware
{
    /// <summary>
    /// Reinstates CORS headers whenever an error occurs.
    /// </summary>
    /// <remarks>ASP.NET strips off CORS on errors; this overcomes this issue,
    ///  explained and worked around at https://github.com/aspnet/Home/issues/2378 </remarks>
    public class MaintainCorsHeadersMiddleware
    {
        public MaintainCorsHeadersMiddleware(RequestDelegate next)
        {
            _next = next;
        }
        private readonly RequestDelegate _next;

        public async Task Invoke(HttpContext httpContext)
        {
            // Find and hold onto any CORS related headers ...
            var corsHeaders = new HeaderDictionary();
            foreach (var pair in httpContext.Response.Headers)
            {
                if (!pair.Key.ToLower().StartsWith("access-control-")) { continue; } // Not CORS related
                corsHeaders[pair.Key] = pair.Value;
            }

            // Bind to the OnStarting event so that we can make sure these CORS headers are still included going to the client
            httpContext.Response.OnStarting(o => {
                var ctx = (HttpContext)o;
                var headers = ctx.Response.Headers;
                // Ensure all CORS headers remain or else add them back in ...
                foreach (var pair in corsHeaders)
                {
                    if (headers.ContainsKey(pair.Key)) { continue; } // Still there!
                    headers.Add(pair.Key, pair.Value);
                }
                return Task.CompletedTask;
            }, httpContext);

            // Call the pipeline ...
            await _next(httpContext);
        }
    }
}

Und dann habe ich es meiner Site-Konfiguration in Startup.cs hinzugefügt:

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseCors(...);
        app.UseMiddleware<MaintainCorsHeadersMiddleware>();

        ...
        app.UseMvc();
    }
10
Patrick Szalapski 18 Sept. 2019 im 12:01

ASP.NET Core 2.2.0 Antwort

Dieses Problem wurde jetzt behoben. CORS-Header werden jetzt zurückgegeben, auch wenn Ausnahmen ausgelöst werden und eine Antwort von 500 zurückgegeben wird.

ASP.NET Core <= 2.1.0 Antwort

CORS-Header wurden aus der Antwort entfernt, wenn eine Ausnahme ausgelöst und eine 500-Antwort zurückgegeben wird.

2
Muhammad Rehan Saeed 23 Jän. 2019 im 13:42

In meinem Fall gingen die CORS-Header verloren, weil ich eine Anforderungstypanforderung "application / json" gestellt habe. In CORS sendet diese Art von Anforderung zuerst eine OPTIONS-Methode. Danach wird der reguläre POST angefordert. Die OPTIONEN wurden jedoch von einem Middleware-Code in meiner .Net Core-Pipeline mit folgender Funktion verwaltet:

        if (context.Request.Method == "OPTIONS")
        {
            context.Response.StatusCode = (int)HttpStatusCode.OK;
            await context.Response.WriteAsync(string.Empty);
        } 

Sobald ich die Middleware entfernt habe, wurden diese Anfragen fehlerfrei bearbeitet.

0
Fidel Orozco 15 Juni 2018 im 20:58

Ich hatte das gleiche Problem bei einem Web-API-Projekt mit OWIN-Middleware, bei dem eine falsche Paketversion Fehler auf der API-Seite verursachte (auf der Clientseite ausgeblendet, da CORS-Header in der Antwort entfernt wurden, wodurch der ursprüngliche Fehler verdeckt wurde). Ich habe eine ähnliche Lösung wie Ihre implementiert und hier geteilt, weil ich mit OWIN im Web kein ähnliches Beispiel finden konnte:

using System;
using System.Linq;
using System.Threading.Tasks;
using Owin;
using Microsoft.Owin;
using Microsoft.Owin.Cors;

namespace App_Server
{
    using AppFunc = Func<IDictionary<string, object>, Task>;
    partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.UseCors(CorsOptions.AllowAll);
            app.Use(new Func<AppFunc, AppFunc>(RetainHeaders));
            ....
            (other startup tasks)
        }

        private AppFunc RetainHeaders(AppFunc next)
        {
            AppFunc appFunc = async (IDictionary<string, object> context) =>
            {
                IOwinContext httpContext = new OwinContext(context);
                var corsHeaders = new HeaderDictionary(new Dictionary<string, string[]>());

                foreach (var pair in httpContext.Response.Headers)
                {
                    if (!pair.Key.ToLower().StartsWith("access-control-")) { continue; } //not a CORS header
                    corsHeaders[pair.Key] = pair.Value.First();
                }

                httpContext.Response.OnSendingHeaders(o =>
                {
                    var localcontext = new OwinContext((IDictionary<string, object>)o);
                    var headers = localcontext.Response.Headers;
                    //make sure headers are present, and if not, add them back
                    foreach (var pair in corsHeaders)
                    {
                        if (headers.ContainsKey(pair.Key)) { continue; }
                        headers.Add(pair.Key, pair.Value);
                    }
                }, context);

                await next.Invoke(context);
            };
            return appFunc;
        }
}

Angesichts der schlechten Dokumentation der OWIN-Pakete für .Net war dies ein ziemlicher Prozess. Ich hoffe, es hilft jemand anderem, der darauf stößt, nach einer Lösung zu suchen.

0
Ryan I. 24 Juli 2019 im 17:17