Ce serait un double de Comment l'en-tête Access-Control-Allow-Origin fonctionne?, mais la méthode là-bas ne fonctionne pas non plus pour moi. J'espère qu'il me manque quelque chose.

J'essaie d'obtenir un en-tête Access-Control-Allow-Origin dans ma réponse à partir de mon API Web .NET Core, à laquelle j'accède via AJAX.

J'ai essayé plusieurs choses. Tous, sauf indication contraire, ont été dans le fichier Startup.cs.

Méthode 1

Conformément à la documentation Microsoft:

public void ConfigureServices(IServiceCollection services)
{
    // Add database
    services.AddDbContext<DbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DbConnection")));

    // Add the ability to use the API with JSON
    services.AddCors();

    // Add framework services.
    services.AddMvc();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();

    if (env.IsDevelopment())
    {
        using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())
        {
            serviceScope.ServiceProvider.GetService<DbContext>().Database.Migrate();
            serviceScope.ServiceProvider.GetService<DbContext>().EnsureSeedData();
        }
    }

    app.UseCors(builder => builder.WithOrigins("https://localhost:44306").AllowAnyMethod());

    app.UseJwtBearerAuthentication(new JwtBearerOptions
    {
        Authority = Configuration["Authentication:AzureAd:AADInstance"] + Configuration["Authentication:AzureAd:TenantId"],
        Audience = Configuration["Authentication:AzureAd:Audience"],
    });

    app.UseMvc();
}

Méthode 2

public void ConfigureServices(IServiceCollection services)
{
    // ...

    services.AddCors(options => options.AddPolicy("AllowWebApp",
        builder => builder.AllowAnyMethod()
                          .AllowAnyMethod()
                          .AllowAnyOrigin()));
                          //.WithOrigins("https://localhost:44306")));

    // ...
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    // ...

    app.UseCors("AllowWebApp");

    // ...
}

J'ai également essayé d'ajouter [EnableCors("AllowWebApp")] sur le contrôleur et la méthode.

Du facteur, je reçois:

encodage de contenu → gzip
content-type → text / plain; jeu de caractères = utf-8
date → mer.25 janvier 2017 04:51:48 GMT
serveur → Kestrel
état → 200
varier → Accepter-Encodage
x-powered-by → ASP.NET
x-sourcefiles → =? UTF-8? B? [SUPPRIMÉ]

Je l'ai également essayé dans Chrome et j'ai obtenu des en-têtes similaires.

Si cela compte, la méthode à laquelle j'essaie d'accéder a un attribut Authorize dessus. Mais cette partie devrait fonctionner correctement (j'obtiens au moins une bonne réponse)

Alors, est-ce que je rate quelque chose de très évident, ou est-ce que cela s'est cassé? J'utilise actuellement la version 1.1.0.


Modifier l'ajout de JS et de Controller Stub

function getContactPreviews(resultsCallback) {
    var xmlhttp = new XMLHttpRequest();

    xmlhttp.onreadystatechange = () => {
        if (xmlhttp.readyState == XMLHttpRequest.DONE && xmlhttp.status == 200) {
            resultsCallback(JSON.parse(xmlhttp.response));
        }
    }

    xmlhttp.open("GET", "https://localhost:44357/api/User/ContactsPreview", true);
    xmlhttp.setRequestHeader("Authorization", "Bearer " + localStorage.getItem("AuthorizationToken"));
    xmlhttp.send();
}

Contrôleur Stub

[Authorize]
[Route("api/[controller]")]
public class UserController : ApiController
{
    [HttpGet(nameof(ContactsPreview))]
    [EnableCors("AllowWebApp")]
    public IEnumerable<Customer> ContactsPreview()
    {
        // ...
    }
}
30
David 25 janv. 2017 à 08:21

4 réponses

Meilleure réponse

Le problème est que lors de l'utilisation de l'authentification au porteur (ou toute autre que j'imagine), elle ajoute un en-tête "Authorization", et le serveur ne donnera un accord que si la configuration permet cet en-tête.

Il y a deux façons de résoudre le problème, et ci-dessous le seul code nécessaire. Il va dans la méthode Configure() dans Startup.cs dans la solution API Web.

Méthode 1: Autoriser tous les en-têtes

app.UseCors(builder => builder.WithOrigins("https://localhost:44306")
                                .AllowAnyMethod()
                                .AllowAnyHeader());

Méthode 2: Autoriser des en-têtes spécifiques

app.UseCors(builder => builder.WithOrigins("https://localhost:44306")
                              .AllowAnyMethod()
                              .WithHeaders("authorization", "accept", "content-type", "origin"));

Les en-têtes supplémentaires sont parce que, selon la documentation:

Les navigateurs ne sont pas entièrement cohérents dans la façon dont ils définissent les en-têtes de demande de contrôle d'accès. Si vous définissez les en-têtes sur autre chose que "*", vous devez inclure au moins "accept", "content-type" et "origin", ainsi que tous les en-têtes personnalisés que vous souhaitez prendre en charge.

27
David 26 janv. 2017 à 06:20

À partir du 17/03/2019, .NET Core version 2.1:

Cela permettra peut-être de gagner du temps pour d'autres pauvres âmes ... à un moment donné, j'ai commencé à être frustré et j'ai presque abandonné .NET Core WebApi en tant que projet séparé.

Dans des circonstances réelles, il existe d'autres configurations dans les fonctions de démarrage, par ex. J'avais des enregistrements Swagger, DI, etc. Je n'ai pas réussi à faire fonctionner quelque chose de sanglant jusqu'à ce que je mette les méthodes AddCors () et UseCors () pour être la première à être appelée dans les fonctions de configuration.

 // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddCors(options =>
            {
                options.AddPolicy("SomePolicy",
                    builder => builder.AllowAnyOrigin()
                        .AllowAnyMethod()
                        .AllowAnyHeader()
                        .AllowCredentials());
            });



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

Après cela, les appels de l'application Angular 6 (appels client Swagger Typescript) ont commencé à fonctionner comme un charme.

1
VladVIII 17 mars 2019 à 23:02

L'en-tête Access-Control-Allow-Origin est renvoyé uniquement si:

  1. La demande comprend un en-tête "Origin".
  2. L'origine demandée correspond à la politique CORS.

Ensuite, le serveur renvoie l'en-tête ACAO avec l'URL d'origine comme valeur.

L'en-tête Origin est généralement défini par l'objet XMLHttpRequest.

Pour plus d'informations, voir Fonctionnement de CORS

9
Luis Cantero 23 mars 2018 à 09:34

Dans le fichier Startup.cs, ajoutez ce qui suit

public CorsPolicy GenerateCorsPolicy(){
                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();
                return corsBuilder.Build();
    }

Dans la méthode ConfigureServices:

 services.AddCors(options =>
                {
                    options.AddPolicy("AllowAllOrigins", GenerateCorsPolicy());
                });

// Pour appliquer CORS globalement dans toute l'application // Dans la méthode Configure, ajoutez

app.UseCors("AllowAllOrigins");  

[DisableCors]
En utilisant l'attribut DisableCors, nous pouvons désactiver CORS pour un contrôleur ou une action.

// Pour activer la base du contrôleur CORS - Si vous appliquez globalement, vous n'avez pas besoin de celui-ci.

[EnableCors("AllowAllOrigins")]  
public class HomeController: Controller {}  
2
Tejas Patel 5 juin 2018 à 19:44