267 votes

Comment activer CORS dans ASP.net Core WebAPI

Ce que je suis en train de faire

J'ai un backend ASP.Net de Base de l'API Web hébergé sur Azure Plan Libre (Code Source: https://github.com/killerrin/Portfolio-Backend).

J'ai aussi un Site web pour les Clients qui je veux faire consommer de l'API. Le Client Demande ne sera pas hébergé sur Azure, mais plutôt sera hébergé sur Github Pages ou sur un autre Service d'Hébergement Web que j'ai accès. De ce fait les noms de domaine ne s'alignent pas.

La recherche dans ce, j'ai besoin d'activer la SCRO sur le Web API côté, cependant, j'ai essayé à peu près tout depuis plusieurs heures maintenant et il refuse de travailler.

Comment j'ai de l'Installation du Client C'est juste un simple client écrit en React.js. Je suis l'appel de l'Api par AJAX en Jquery. La Réagir site fonctionne si je sais que ses pas que. Le Jquery, les appels de l'API travaille comme je l'ai confirmé dans la Tentative 1. Voici comment je l'appelle

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

Ce que j'ai essayé


Tentative 1 - Le " bon " chemin

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

J'ai suivi ce tutoriel sur le Site web de Microsoft à un T, en essayant tous les 3 options de permettre à l'échelle Mondiale dans le Démarrage.cs, pour l'installer sur chaque contrôleur et l'Essayer sur chaque Action.

Suivant cette méthode, la Croix de Domaine fonctionne, mais seulement sur une seule Action sur un seul contrôleur (POST à la AccountController). Pour tout le reste, l' Microsoft.AspNetCore.Cors middleware refuse de définir les en-têtes.

J'ai installé Microsoft.AspNetCore.Cors via NUGET et la version est - 1.1.2

Voici comment je l'ai de configuration de Démarrage.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();

        ...
        ...
        ...
    }

Comme vous pouvez le voir, je fais tout ce que dit. - Je ajouter de la Scro avant MVC deux fois, et quand cela ne fonctionne pas j'ai essayé de mettre [EnableCors("MyPolicy")] sur chaque contrôleur comme

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

Tentative 2 - Brute Forcer

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

Après plusieurs heures de l'essayer lors de la dernière tentative, j'ai pensé que je voudrais essayer de bruteforce en essayant de définir les en-têtes manuellement, en les forçant à exécuter sur chaque réponse. Je l'ai fait en suivant ce tutoriel comment ajouter manuellement des en-têtes à chaque réponse.

Ce sont les en-têtes, j'ai ajouté

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

Ce sont d'autres têtes que j'ai essayé qui a échoué

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

Avec cette méthode, la Croix-têtes de Site sont appliqués correctement et qu'ils se présentent dans mon developer console et en Facteur. Le problème, toutefois, est que bien qu'il passe à l' Access-Control-Allow-Origin vérification, le contrôle webbrowser jette un hissy fit sur (je crois) Access-Control-Allow-Headers indiquant 415 (Unsupported Media Type)

De sorte que la force brute de la méthode ne fonctionne pas non plus


Enfin

Quelqu'un a eu cela fonctionne et pourrait donner un coup de main, ou simplement être en mesure de me pointer dans la bonne direction?


MODIFIER

Donc, pour obtenir les appels d'API pour passer à travers, j'ai dû l'arrêter à l'aide de JQuery et de passer à un Pur Javascript XMLHttpRequest format.

Tentative 1

J'ai réussi à obtenir l' Microsoft.AspNetCore.Cors de travail en suivant MindingData de réponse, sauf à l'intérieur de l' Configure Méthode de mettre la app.UseCors avant app.UseMvc.

En outre, lorsqu'il est mélangé avec l'API Javascript Solution options.AllowAnyOrigin() pour les génériques de soutien ont commencé à travailler ainsi.

Tentative 2

J'ai donc réussi à obtenir Tentative 2 (force brute) pour le travail... à la seule exception que le caractère Générique pour Access-Control-Allow-Origin ne fonctionne pas et comme j'ai pour définir manuellement les domaines qui y ont accès.

Son évidemment pas idéal car je veux juste ce WebAPI être ouvert à tout le monde, mais il atleast fonctionne pour moi sur un site distinct, ce qui signifie que c'est un début

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

296voto

MindingData Points 331

Parce que vous avez un très simple de la SCRO politique (Permettre à toutes les demandes de XXX de domaine), vous n'avez pas besoin de faire si compliqué. Essayez de faire la suite (Un très de base de la mise en œuvre de la SCRO).

Si vous ne l'avez pas déjà fait, installez le CORS de package nuget.

Install-Package Microsoft.AspNetCore.Cors

Dans le ConfigureServices méthode de démarrage.cs, ajoutez de la SCRO services.

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

Puis dans votre méthode Configure () de votre démarrage.cs, ajoutez la ligne suivante :

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

Maintenant de lui donner un aller. Les politiques sont pour quand vous voulez des politiques différentes pour les différentes actions (par exemple, les différents hôtes ou différents en-têtes). Pour votre exemple simple que vous n'avez vraiment pas besoin. Démarrer avec cet exemple simple et ajuster si vous avez besoin à partir de là.

Pour en savoir plus : http://dotnetcoretutorials.com/2017/01/03/enabling-cors-asp-net-core/

262voto

Ji Ra Points 1687
  • Dans ConfigureServices ajouter services.AddCors(); AVANT les services.AddMvc();
  • Ajouter UseCors à Configurer

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

Point principal est que ajouter app.UseCors, avant d' app.UseMvc().

Assurez-vous de déclarer la SCRO fonctionnalités avant MVC ainsi, le middleware, les feux avant de la MVC pipeline obtient le contrôle et se termine à la demande.

Après la méthode ci-dessus fonctionne, vous pouvez le changer configurer une ORIGINE particulière pour accepter les appels d'api et d'éviter de laisser votre API donc ouvert à toute personne

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

Dans la configuration de la méthode de raconter de la SCRO à utiliser la stratégie que vous venez de créer:

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

Je viens de trouver ce petit article sur le sujet - https://dzone.com/articles/cors-in-net-core-net-core-security-part-vi

37voto

user8266077 Points 239

J'ai créé ma propre classe de middleware qui a fonctionné pour moi. Je pense que quelque chose ne va pas avec la classe de middleware .net core

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

et utilisé de cette façon dans le startup.cs

 app.UseCorsMiddleware();
 

22voto

Towhid Points 634

Dans mon cas, seule la demande get fonctionne bien selon la réponse de MindingData. Pour les autres types de demande, vous devez écrire:

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

N'oubliez pas d'ajouter .AllowAnyHeader()

13voto

ckr Points 81

Pour développer sur user8266077's réponse, j'ai trouvé que j'ai encore besoin de fournir des OPTIONS de réponse pour le contrôle en amont des demandes de dans le .NET de Base 2.1-aperçu dans mon cas d'utilisation:

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

et puis activé le middleware comme dans de Démarrage.cs

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X