Les en-têtes CORS sont manquants lors du déploiement sur Azure Web App / API Azure

J’ai créé un WebAPI hébergé sur WebAPI 2 . Il existe également une application Web ( AngularJS ) qui utilise l’API et joue le rôle de client.

J’ai ajouté le code nécessaire pour le système CORS au Startup.cs et je l’ai hébergé dans un IIS local sur un port différent de celui du client, ce qui confirme le fait qu’il résout le problème Cors .

Ensuite, j’ai déployé les deux applications sur Azure (j’ai mis les deux sur Azure en tant qu’application Web et j’ai également essayé de mettre l’OWIN sur l’API Azure actuellement en prévisualisation), mais la demande de contrôle en amont échoue à présent (pas Access-Control-Allow-Origin présent dans la réponse).

Q: Existe t-il des spécificités d’Azure dont je ne suis pas au courant? Comment se fait-il que OWIN ne serve pas cet en-tête lors du déploiement mais qu’il fonctionne sur localhost? Je ne vois aucune contrainte dans la fenêtre de propriétés sur les parameters de lames Azure pour les applications.

Remarques:

À propos de certains détails de la configuration que j’utilise:

  • Utiliser Owin , WebAPI2 , Ninject , Ninject
  • Un jeton personnalisé est émis et fourni dans les en-têtes à chaque demande ultérieure et est vérifié avec un filtre personnalisé.
  • Cors je tente pour l’instant est *

La partie pertinente de Startup.cs:

 public void Configuration(IAppBuilder appBuilder) { appBuilder.UseCors(CorsOptions.AllowAll); HttpConfiguration config = new HttpConfiguration(); config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; //bind IClientsNotifier with method returning singleton instance of hub var ninjectKernel = NinjectWebCommon.GetKernel(); ninjectKernel.Bind().ToSelf().InSingletonScope(); ninjectKernel.Bind().ToSelf(); GlobalHost.DependencyResolver = new NinjectSignalRDependencyResolver(ninjectKernel); appBuilder.Map( "/signalr", map => { map.UseCors(CorsOptions.AllowAll); var hubConfiguration = new HubConfiguration(); map.RunSignalR(hubConfiguration); }); config.MapHttpAtsortingbuteRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); config.Formatters.Remove(config.Formatters.XmlFormatter); config.Filters.Add(new NoCacheHeaderFilter()); //the IE9 fix for cache var resolver = new NinjectDependencyResolver(NinjectWebCommon.GetKernel()); config.Filters.Add((System.Web.Http.Filters.IFilter)resolver.GetService(typeof(WebApiAuthenticationFilter))); appBuilder.UseNinjectMiddleware(NinjectWebCommon.GetKernel); appBuilder.UseNinjectWebApi(config); } 

De plus, j’ai commenté la ligne suivante de web.config afin de prendre en charge la requête HTTP OPTIONS (sinon, l’erreur HTTP 405 était générée)

   <!----> ... 

En fait, le site Web Azure est supposé gérer la CORS pour vous. Je pense que vous avez manqué une lame pratique du site Azure:

Azure Websites CORS lame

Si notre propre compréhension est correcte, le problème de ce middleware Azure est qu’il ne vous permet de configurer que les origines autorisées. Il manque une configuration gérable “en-têtes autorisées”, des règles par URL et d’autres en-têtes HTTP CORS utiles. Pire: il supprime tous les en-têtes liés à CORS de chaque réponse HTTP traitée, avant de définir sa propre réponse, de sorte qu’il ne vous laisse même pas gérer ce qu’il ne fait pas.

La bonne chose à faire est que vous pouvez complètement désactiver ce middleware et gérer CORS par vos propres moyens. Il vous suffit de supprimer chaque origine autorisée (y compris * ) de la lame de parameters CORS du portail. Ensuite, vous pouvez utiliser web.config ou Web Api pour le gérer plus spécifiquement. Voir la documentation :

N’essayez pas d’utiliser les API Web CORS et App Service CORS dans une seule application API. Le service d’application CORS aura la priorité et la Web API CORS n’aura aucun effet. Par exemple, si vous activez un domaine d’origine dans App Service et tous les domaines d’origine dans le code de votre API Web, votre application API Azure acceptera uniquement les appels du domaine que vous avez spécifié dans Azure.

Voir aussi cette question connexe :

La réponse finale est donc la suivante: si votre application n’a pas besoin d’une gestion CORS très spécifique, vous pouvez utiliser Azure App Service CORS. Sinon, vous devrez vous en occuper vous-même et désactiver toute la configuration CORS dans l’application Web.

En fin de compte, je suis allé avec un moyen plus simple – enlevé toute la gestion du code de CORS et tout simplement mettre les en-têtes dans le web.config :

           ... 

(notez que allow-origin n’a pas de barre oblique à la fin de l’URL!)

La partie allow-credentials visait à satisfaire le signal SignalR; probablement, il pourrait s’en passer.

Si quelqu’un trouve une raison pour laquelle la méthode codée ne fonctionne pas, j’aimerais savoir!

J’ai aussi rencontré ce problème. Je pense enfin que le CORS de WebAPI programmatique fonctionne dans un Azure App Service avec cette combinaison magique de changements de gestionnaire:

     

Vous devez supprimer OPTIONSVerbHandler pour supprimer les réponses de contrôle en amont par défaut. En utilisant des en-têtes personnalisés dans le fichier web.config, vous venez de trouver un autre moyen de vous assurer que ces en-têtes sont écrits dans les demandes OPTIONS qui n’atteignent jamais votre application.

La clé est de s’assurer que les demandes OPTIONS sont gérées par un autre moyen, et je pense que cela est possible en rajoutant ExtensionlessUrlHandler en spécifiant OPTIONS dans la liste des verbes. Je ne connais pas bien IIS et je spécule donc sur le mécanisme, mais cela semble fonctionner. FWIW, je suis en train de développer la fonctionnalité CORS de WebAPI dans App_Start / WebApiConfig.cs comme ceci:

 config.EnableCors(new MyCorsPolicyProvider()); 

MyCorsPolicyProvider est une classe qui implémente ICorsPolicyProvider .

Je règle ceci sur le portail azure, mais le contrôle en amont de chrome échoue toujours pour la requête interdomaine. Dans le document azuree, le contrôle en amont utilise OPTION http verb, je suppose que chrome peut simplement utiliser un object GET. Il n’ya donc pas de valeur d’en-tête pour cela.

Mon problème était que j’avais accidentellement mis http au lieu de https dans le lame de configuration de page personnalisée Azure AD B2C … Après modification en https, cela fonctionnait à merveille.

essayez cette commande sur le shell cloud AZURE

 az resource update --name web --resource-group ResourceGroup --namespace Microsoft.Web --resource-type config --parent sites/ --set properties.cors.allowedOrigins="['http://localhost:5000']" --api-version 2015-06-01