web-dev-qa-db-fra.com

Activer l'en-tête OPTIONS pour CORS sur .NET Core Web API

J'ai résolu ce problème après ne pas avoir trouvé la solution sur Stackoverflow, donc je partage mon problème ici et la solution dans une réponse.

Après avoir activé une stratégie inter-domaines dans mon application .NET Core Web Api avec AddCors, elle ne fonctionne toujours pas à partir des navigateurs. En effet, les navigateurs, y compris Chrome et Firefox, enverront d'abord une demande OPTIONS et mon application répond simplement avec 204 Aucun contenu.

16
Niels Brinch

Ajoutez une classe middleware à votre projet pour gérer le verbe OPTIONS .

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

namespace Web.Middlewares
{
    public class OptionsMiddleware
    {
        private readonly RequestDelegate _next;

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

        public Task Invoke(HttpContext context)
        {
            return BeginInvoke(context);
        }

        private Task BeginInvoke(HttpContext context)
        {
            if (context.Request.Method == "OPTIONS")
            {
                context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { (string)context.Request.Headers["Origin"] });
                context.Response.Headers.Add("Access-Control-Allow-Headers", new[] { "Origin, X-Requested-With, Content-Type, Accept" });
                context.Response.Headers.Add("Access-Control-Allow-Methods", new[] { "GET, POST, PUT, DELETE, OPTIONS" });
                context.Response.Headers.Add("Access-Control-Allow-Credentials", new[] { "true" });
                context.Response.StatusCode = 200;
                return context.Response.WriteAsync("OK");
            }

            return _next.Invoke(context);
        }
    }

    public static class OptionsMiddlewareExtensions
    {
        public static IApplicationBuilder UseOptions(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<OptionsMiddleware>();
        }
    }
}

Ajoutez ensuite app.UseOptions(); this comme première ligne dans Startup.cs dans la méthode Configure.

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    app.UseOptions();
}
21
Niels Brinch

Je sais qu'il a été répondu. Il suffit de répondre avec les informations mises à jour. Cela aiderait donc les autres.

Son maintenant intégré dans le cadre de base asp.net.

Suivez simplement https://docs.Microsoft.com/en-us/aspnet/core/security/cors

et remplacer

    app.UseCors(builder =>
   builder.WithOrigins("http://example.com"));

avec

        app.UseCors(builder =>
       builder.WithOrigins("http://example.com")
              .AllowAnyHeader()
              .AllowAnyMethod()
              .AllowCredentials());
5
Jeyara

Cela a fonctionné pour moi:

Assurez-vous que ceci:

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

Se produit avant l'un de ces événements:

app.UseHttpsRedirection();
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseCookiePolicy();

N'oubliez pas que nous avons affaire à un "pipeline". Le cors doit être le premier.

-gimzani

1
user1628627

Il n'y a pas besoin d'un middleware supplémentaire. Comme déjà mentionné ci-dessus, la seule chose nécessaire est la méthode OPTIONS autorisée dans la configuration Cors. Vous pouvez AllowAnyMethod comme suggéré ici: https://stackoverflow.com/a/55764660/1192191

Mais il est plus sûr de simplement autoriser les éléments spécifiques comme celui-ci:

app.UseCors(builder => builder
.WithOrigins("https://localhost", "https://production.company.com") /* list of environments that will access this api */
.WithMethods("GET", "OPTIONS") /* assuming your endpoint only supports GET */
.WithHeaders("Origin", "Authorization") /* headers apart of safe-list ones that you use */
);

Certains en-têtes sont toujours autorisés: https://developer.mozilla.org/en-US/docs/Glossary/CORS-safelisted_request_header

0
Taras Zavorotnii

Je voulais autoriser cela pour une seule méthode, sans utiliser de middleware pour autoriser cela sur n'importe quelle méthode. Voici ce que j'ai fini de faire:

Manipulation manuelle de la méthode "OPTIONS"

[HttpOptions("/find")]
public IActionResult FindOptions()
{
    Response.Headers.Add("Access-Control-Allow-Origin", new[] { (string)Request.Headers["Origin"] });
    Response.Headers.Add("Access-Control-Allow-Headers", new[] { "Origin, X-Requested-With, Content-Type, Accept" });
    Response.Headers.Add("Access-Control-Allow-Methods", new[] { "POST, OPTIONS" }); // new[] { "GET, POST, PUT, DELETE, OPTIONS" }
    Response.Headers.Add("Access-Control-Allow-Credentials", new[] { "true" });
    return NoContent();
}
[HttpPost("/find")]
public async Task<IActionResult> FindOptions([FromForm]Find_POSTModel model)
{
    AllowCrossOrigin();

    // your code...
}

private void AllowCrossOrigin()
{
    Uri Origin = null;
    Uri.TryCreate(Request.Headers["Origin"].FirstOrDefault(), UriKind.Absolute, out Origin);

    if (Origin != null && IsOriginAllowed(Origin))
        Response.Headers.Add("Access-Control-Allow-Origin", $"{Origin.Scheme}://{Origin.Host}");
}

Et bien sûr, vous pouvez implémenter IsOriginAllowed comme vous le souhaitez

private bool IsOriginAllowed(Uri Origin)
{
    const string myDomain = "mydomain.com";
    const string[] allowedDomains = new []{ "example.com", "sub.example.com" };

    return 
           allowedDomains.Contains(Origin.Host) 
           || Origin.Host.EndsWith($".{myDomain}");
}

Vous pouvez trouver plus de détails sur comment activer CORS pour POST requêtes sur un seul point de terminaison

0
Jean