J'ai déployé mon API web ASP.NET Core sur Azure, et je peux accéder à ses points de terminaison à l'aide de Swagger ou d'un débogueur web comme Fiddler. Dans les deux cas (même origine dans Swagger, origine différente en utilisant Fiddler à partir de mon ordinateur), lorsque j'accède aux API, j'obtiens le résultat escompté, avec CORS activé comme suit dans mon fichier Startup.cs
:
-
ajouter
services.AddCors();
aConfigureServices
. -
ajouter le middleware à
Configure
: Je suis conscient que l'ordre est important ici ( ASP.NET 5 : Access-Control-Allow-Origin dans la réponse ), je place donc cet appel au sommet de la méthode, précédé seulement par l'enregistrement ou le diagnostic du middleware ; voici ma méthode complète :public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IDatabaseInitializer databaseInitializer) { loggerFactory.AddConsole(Configuration.GetSection("Logging")); loggerFactory.AddDebug(); loggerFactory.AddNLog();
// to serve up index.html app.UseDefaultFiles(); app.UseStaticFiles(); // http://www.talkingdotnet.com/aspnet-core-diagnostics-middleware-error-handling/ app.UseDeveloperExceptionPage(); app.UseDatabaseErrorPage(); // CORS // https://docs.asp.net/en/latest/security/cors.html app.UseCors(builder => builder.WithOrigins("http://localhost:4200", "http://www.myclientserver.com") .AllowAnyHeader() .AllowAnyMethod()); app.UseOAuthValidation(); app.UseOpenIddict(); app.UseMvc(); databaseInitializer.Seed().GetAwaiter().GetResult(); env.ConfigureNLog("nlog.config"); // swagger app.UseSwagger(); app.UseSwaggerUi();
}
En localhost
CORS est utilisé pendant le développement et fait référence à une application Angular2 CLI. CORS fonctionne bien localement, et mes applications client et API sont sur des ports différents sur le même localhost, il s'agit donc d'une origine croisée "vraie" (je fais cette remarque en raison des suggestions que j'ai trouvées ici : https://weblog.west-wind.com/posts/2016/Sep/26/ASPNET-Core-and-CORS-Gotchas : l'auteur du message remarque que l'en-tête CORS dans la réponse est envoyé uniquement lorsque cela est réellement nécessaire, c'est-à-dire dans de véritables environnements inter-origines).
En utilisant Fiddler, je peux accéder avec succès à l'API distante, mais je n'obtiens aucun résultat. Access-Control-Allow-Origin
en-tête. Ainsi, lorsque j'appelle l'API depuis le navigateur (par le biais de mon application client), la demande AJAX échoue, même si le serveur renvoie 200. Exemple de requête Fiddler (succès) :
GET http://mywebapisiteurl/api/values HTTP/1.1
User-Agent: Fiddler
réponse :
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/8.0
X-Powered-By: ASP.NET
Set-Cookie: ARRAffinity=3d551180c72208c1d997584c2b6119cf44e3a55c868f05ffc9258d25a58e95b1;Path=/;Domain=prinapi.azurewebsites.net
Date: Thu, 01 Dec 2016 10:30:19 GMT
["value1","value2"]
Lorsque j'essaie d'accéder à l'API distante déployée sur Azure, mon application cliente échoue toujours sa requête AJAX avec une erreur :
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://www.myclientserver.com' is therefore not allowed access.
Voici un exemple de code client utilisant Angular2 (en utilisant Plunker) :
import {Component, NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import { Http, Headers, Response } from '@angular/http';
import { HttpModule } from '@angular/http';
@Component({
selector: 'my-app',
template: `
<div>
<h2>Hello {{name}}</h2>
<button (click)="test()">test</button>
</div>
`,
})
export class App {
name:string;
constructor(private _http: Http) {
this.name = 'Angular2'
}
public test() {
this._http.get('http://theapisiteurlhere/api/values',
{
headers: new Headers({
'Content-Type': 'application/json'
})
})
.subscribe(
(data: any) => {
console.log(data);
},
error => {
console.log(error);
});
}
}
@NgModule({
imports: [ BrowserModule, HttpModule ],
declarations: [ App ],
bootstrap: [ App ]
})
export class AppModule {}
En résumé, il semble que le serveur de l'API ASPNET ne renvoie pas les en-têtes CORS attendus, et que mon client basé sur un navigateur hébergé sur une origine différente échoue donc. Pourtant, la configuration CORS semble correcte, du moins si l'on en croit la documentation citée plus haut ; je suis dans un véritable environnement multi-origine ; et je place l'intergiciel avant les autres. Peut-être que quelque chose d'évident m'échappe, mais en cherchant sur Google, je n'ai trouvé que ces recommandations. Un conseil ?
UPDATE
En réponse à @Daniel J.G : la demande/réponse de fiddler est réussie :
GET http://theapiserver/api/values HTTP/1.1
User-Agent: Fiddler
Host: theapiserver
Origin: http://theappserver/apps/prin
et :
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/8.0
Access-Control-Allow-Origin: http://theappserver/apps/prin
X-Powered-By: ASP.NET
Set-Cookie: ARRAffinity=3d551180c72208c1d997584c2b6119cf44e3a55c868f05ffc9258d25a58e95b1;Path=/;Domain=theapiserver
Date: Thu, 01 Dec 2016 14:15:21 GMT
Content-Length: 19
["value1","value2"]
La demande/réponse d'Angular2 (Plunker) échoue plutôt, comme signalé. En inspectant le trafic réseau, je peux voir la demande de contrôle préalable uniquement :
OPTIONS http://theapiserver/api/values HTTP/1.1
Host: theapiserver
Proxy-Connection: keep-alive
Access-Control-Request-Method: GET
Origin: http://run.plnkr.co
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36
Access-Control-Request-Headers: content-type
Accept: */*
Referer: http://run.plnkr.co/h17wYofXGFuTy2Oh/
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8,it;q=0.6
HTTP/1.1 204 No Content
Server: Microsoft-IIS/8.0
X-Powered-By: ASP.NET
Set-Cookie: ARRAffinity=3d551180c72208c1d997584c2b6119cf44e3a55c868f05ffc9258d25a58e95b1;Path=/;Domain=theapiserver
Date: Thu, 01 Dec 2016 14:23:02 GMT
Après cela, la demande échoue et plus aucun trafic n'est acheminé vers le serveur. Le problème signalé est le suivant Response to preflight request doesn't pass access control check
à cause de l'absence de l'en-tête dans la réponse :
XMLHttpRequest cannot load http://theapiserver/api/values. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://run.plnkr.co' is therefore not allowed access.
0 votes
Avez-vous essayé de régler les en-têtes host et origin dans fiddler (host sur l'hôte de l'api et origin sur un autre pour simuler le cross origin) ? Cela pourrait également aider si vous postez les détails d'une requête faite à partir d'angular.
0 votes
Merci, j'ai mis à jour mon post (voir en bas). En bref, avec Fiddler, tout va bien ; avec Angular2, la demande de contrôle préalable échoue car il n'y a pas d'en-tête ACAO dans la réponse du serveur, bien que CORS soit activé.
0 votes
Vous êtes sûr de l'origine
http://run.plnkr.co
est l'une des origines autorisées ?7 votes
Les gars, j'ai trouvé la solution : Je n'avais pas remarqué que dans le portail Azure il y a une section CORS. Si je n'y entre pas d'origine autorisée, ma configuration basée sur le code ne semble pas avoir d'importance. Cela me semble étrange, car je suis obligé de dupliquer les URL ici, mais une fois que j'ai ajouté * aux origines autorisées là-bas, cela a fonctionné.
1 votes
Je suppose qu'Azure se place devant votre application et fait sa propre vérification CORS.
0 votes
En mettant la même chose dans les cors sur azure, ça m'a résolu aussi. merde.
0 votes
@Naftis, il est préférable de mettre ce que vous avez trouvé dans une réponse séparée et de la marquer comme la réponse de cette question. Sinon, il est difficile de remarquer la raison de cette question dans les commentaires.
0 votes
J'ai également ce problème mais je n'utilise pas Azure... asp.net core s'exécute comme un service Windows. Le code de base est identique à celui de l'OP en ce qui concerne CORS.