web-dev-qa-db-fra.com

CORS dans .NET Core

J'essaie d'activer CORS dans .NET Core de la manière suivante:

    public IConfigurationRoot Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors(options => options.AddPolicy("AllowAll", p => p.AllowAnyOrigin()
                                                                    .AllowAnyMethod()
                                                                     .AllowAnyHeader()));     
        services.AddMvc();            
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseCors("AllowAll");

        app.UseMvc(routes =>
         {
             routes.MapRoute(
                 name: "default",
                 template: "{controller=Home}/{action=Index}/{id?}");
         });

    }
}

Cependant, lorsque j'envoie une demande à mon application avec Angular 2, je reçois le fameux

"Aucun en-tête 'Access-Control-Allow-Origin' n'est présent sur la ressource demandée."

message d'erreur.

J'utilise également l'authentification Windows + WebListener. Si je vérifie avec le facteur, les seuls en-têtes de réponse sont:

Longueur de contenu → 3533 type de contenu → application/json; charset = utf-8 Date → vendredi 14 octobre 2016 12:17:57 Serveur GMT → Microsoft-HTTPAPI/2.0

Donc, il doit toujours y avoir quelque chose de mal configuré. Des propositions?

Si je supprime la ligne supprimée, cela fonctionne, mais j'ai besoin de l'authentification Windows :-(

        var Host = new WebHostBuilder()
            .UseWebListener()
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseIISIntegration()
            .UseStartup<Startup>()
            //.UseWebListener(options => options.Listener.AuthenticationManager.AuthenticationSchemes = AuthenticationSchemes.NTLM)
            .Build();
39
David

Supposons que vous ayez la réponse, mais pour le bénéfice des chercheurs, j'ai eu le même problème avec le tutoriel standard sur . NET Core Cors .

Une des nombreuses erreurs rencontrées:

XMLHttpRequest ne peut pas charger localhost: 64633/api/blogs. La réponse à la demande de contrôle en amont ne réussit pas la vérification du contrôle d'accès: aucun en-tête 'Access-Control-Allow-Origin' n'est présent sur la ressource demandée. L'origine 'localhost: 56573' n'est donc pas autorisée. La réponse avait le code d'état HTTP 500.

Après avoir joué, le code suivant a fonctionné. Classe complète affichée ci-dessous pour aider à comprendre ce qui se passe où.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Cors.Infrastructure;

namespace NetCoreWebApiTesting
{
    public class Startup
    {
        public Startup(IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);

            if (env.IsEnvironment("Development"))
            {
                // This will Push telemetry data through Application Insights pipeline faster, allowing you to view results immediately.
                builder.AddApplicationInsightsSettings(developerMode: true);
            }

            builder.AddEnvironmentVariables();
            Configuration = builder.Build();
        }

        public IConfigurationRoot Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container
        public void ConfigureServices(IServiceCollection services)
        {
            // Add framework services.
            services.AddApplicationInsightsTelemetry(Configuration);

            services.AddMvc().AddJsonOptions(options => options.SerializerSettings.ReferenceLoopHandling =
                                                            Newtonsoft.Json.ReferenceLoopHandling.Ignore);

            // ********************
            // Setup CORS
            // ********************
            var corsBuilder = new CorsPolicyBuilder();
            corsBuilder.AllowAnyHeader();
            corsBuilder.AllowAnyMethod();
            corsBuilder.AllowAnyOrigin(); // For anyone access.
            //corsBuilder.WithOrigins("http://localhost:56573"); // for a specific url. Don't add a forward slash on the end!
            corsBuilder.AllowCredentials();

            services.AddCors(options =>
            {
                options.AddPolicy("SiteCorsPolicy", corsBuilder.Build());
            });
        }

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

            app.UseApplicationInsightsRequestTelemetry();

            app.UseApplicationInsightsExceptionTelemetry();

            app.UseMvc();

            // ********************
            // USE CORS - might not be required.
            // ********************
            app.UseCors("SiteCorsPolicy");
        }
    }
}

Pour l'utiliser, vous pouvez ajouter le EnableCorsAttribute sur le contrôleur ou sur la méthode. par exemple.

[EnableCors("SiteCorsPolicy")]
[Route("api/[controller]")]
public class BlogsController : Controller
{

}

ou

// POST api/value
[EnableCors("SiteCorsPolicy")]
[HttpPost]
public HttpResponseMessage Post([FromBody]Blog value)
{
    // Do something with the blog here....

    var msg = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
    return msg;

}

Quand j'ai appelé cela en utilisant le code suivant (en utilisant js/jQuery standard pour faciliter le copier-coller), la communication a cessé d'être rejetée.

function HandleClick() {

    var entityData = {
        "blogId": 2,
        "url": "http://blog.com/blog1",
        "posts": [
        {
            "postId": 3,
            "title": "Post 1-1",
            "content": "This is post 1 for blog 1",
            "blogId": 2
        },
        {
            "postId": 4,
            "title": "Post 1-2",
            "content": "This is post 2 for blog 1",
            "blogId": 2
        }
        ]
    };

    $.ajax({
        type: "POST",
        url: "http://localhost:64633/api/blogs",
        async: true,
        cache: false,
        crossDomain: true,
        data: JSON.stringify(entityData),
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function (responseData, textStatus, jqXHR) {
            var value = responseData;
        },
        error: function (responseData, textStatus, errorThrown) {
            alert('POST failed.');
        }
    });
}
44
HockeyJ

Cette méthode fonctionne normalement, juste essayé sur angular2 avec .net core. Le problème de l'OP est que cela ne fonctionne pas avec l'authentification Windows. Je suppose que le middleware pour l'authentification Windows se produit avant qu'une requête ne soit envoyée, auquel cas il est interrompu. Le meilleur choix serait de voir s'il existe un moyen d'activer le middleware d'autorisation Windows après le traitement du middleware cors dans Configure.

Alors la commande serait

App.UseCors ()

App.UseWindowsAuth ()

App.UseMVC ()

Ils doivent arriver dans cet ordre pour que cela fonctionne.

public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors(options => options.AddPolicy("AllowAll", p => p.AllowAnyOrigin()
                                                                    .AllowAnyMethod()
                                                                     .AllowAnyHeader()));     
        services.AddMvc();            
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseCors("AllowAll");

        app.UseMvc(routes =>
         {
             routes.MapRoute(
                 name: "default",
                 template: "{controller=Home}/{action=Index}/{id?}");
         });

    }
26
sean

Dans ASPNET CORE 2.0, ce qui suit fonctionne pour moi

   public void ConfigureServices(IServiceCollection services)
    {

        services.Configure<MvcOptions>(options =>
        {
            options.Filters.Add(new CorsAuthorizationFilterFactory("AllowSpecificOrigin"));
        });
        services.AddCors(options =>
        {
            options.AddPolicy("AllowSpecificOrigin",
                builder => builder.WithOrigins("http://localhost:5000").AllowAnyHeader()
                .AllowAnyMethod());
        });

        services.AddMvc()
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {

        loggerFactory.AddConsole();
        loggerFactory.AddDebug(LogLevel.Information);

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        // Shows UseCors with named policy.
        app.UseCors("AllowSpecificOrigin");

        app.UseStaticFiles();
        app.UseAuthentication();


        app.UseMvcWithDefaultRoute();
    }
}
14
Tanver Hasan

Ce qui manque à la documentation, c'est l'importance de .AllowAnyMethod (). S'il n'est pas présent, le no redouté 'Access-Control-Allow-Origin' continuera à vous déranger. Dans votre code, c'est là, donc je suppose que vous avez manqué de définir le bon en-tête dans l'application côté client.

Personnellement, je l'ai fait fonctionner en permettant à tous:

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

Et ma Angular post ressemble à ceci:

post(model) {

    let headers = new Headers({
      'Content-Type':'application/json; charset=utf-8;' 
      ,'Accept':'*/*'
    });


    let options = new RequestOptions({ headers: headers });
    let body = JSON.stringify(model);

    return this.http.post(
      'http://localhost:58847/api/TestPost', body, options)
      .map((response: Response) => {
        let res = response.json();
        return res;
      }
    );
}

Après cela, vous progressez graduellement en spécifiant les origines, etc.

13
Stefan de Groot

La réponse de @HockeyJ est correcte, mais vous pouvez faire quelque chose de plus concis si vous le souhaitez.

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    //Or if you want to chose what to include
    services.AddMvcCore()
            .AddCors()
            (...)
}


public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    //Cors
    app.UseCors(builder =>
    {
        builder.AllowAnyHeader();
        builder.AllowAnyMethod();
        builder.AllowCredentials();
        builder.AllowAnyOrigin(); // For anyone access.
        //corsBuilder.WithOrigins("http://localhost:56573"); // for a specific url.
     });
}
2
Gerfaut

Vous devez juste ajouter ceci dans la méthode ConfigureService de la classe StartUp

services.AddCors ();

et cela dans Configure Method of Startup Class et cela fonctionnera bien alors

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

Il n'y a plus rien à ajouter pour activer CORS dans .Net Core

1
Rameshwar