Отсутствующие заголовки CORS при развертывании на веб-приложения Azure и Azure API-интерфейс
Я создал OWIN hosted WebAPI 2
. Существует также веб-приложение (AngularJS
), которое использует API и действует как клиент.
Я добавил необходимый код для CORS
к Startup.cs
, и разместил его в локальных IIS на порту, отличном от клиента, и подтвердил, что он исправляет проблему Cors
.
Затем я развернул оба приложения в Azure (я поместил оба в Azure как веб-приложение, а также попытался поместить OWIN в API Azure, который в настоящее время находится в предварительном просмотре), но ... запрос теперь не выполняется (нет Access-Control-Allow-Origin
в ответе).
Вопрос: есть ли какая-то специфика Azure, о которой я не знаю? Как получилось, что OWIN не обслуживает этот заголовок при развертывании, но работает на localhost? Я не вижу никаких ограничений в окне свойств параметров блейдов Azure для приложений.
Примечания:
О некоторых особенностях настройки, которую я использую:
- использование
Owin
,WebAPI2
,Ninject
,SignalR
- пользовательский токен выдается и предоставляется в заголовки на каждом последующем запросе, и проверяется с помощью пользовательского фильтра.
- Корс, который я пытаюсь сейчас, это
*
Соответствующая часть стартапа.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<MySignalRHub>().ToSelf().InSingletonScope();
ninjectKernel.Bind<QueryStringBearerAuthorizeAttribute>().ToSelf();
GlobalHost.DependencyResolver = new NinjectSignalRDependencyResolver(ninjectKernel);
appBuilder.Map(
"/signalr", map =>
{
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration();
map.RunSignalR(hubConfiguration);
});
config.MapHttpAttributeRoutes();
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);
}
Кроме того, я закомментировал следующую строку из web.config
, Чтобы поддержать запрос HTTP OPTIONS
(в противном случае он вызывал ошибку HTTP 405)
<system.webServer>
<handlers>
<!--<remove name="OPTIONSVerbHandler" />-->
...
5 ответов:
На самом деле веб-сайт Azure должен управлять CORS для вас. Я думаю, вы пропустили удобный веб-сайт Azure blade:
Если наше собственное понимание верно, проблема с этим промежуточным программным обеспечением Azure заключается в том, что оно не позволяет настраивать ничего, кроме разрешенных источников. В нем отсутствует управляемая конфигурация "разрешенных заголовков", правила для каждого URL-адреса и другие полезные заголовки HTTP CORS. Хуже того: он отбрасывает все заголовки, связанные с CORS, из каждого отдельного ответа HTTP, который он обрабатывает, прежде чем устанавливая свои собственные, так что он даже не позволяет вам справиться с тем, что он не делает.
Хорошо то, что вы можете полностью отключить это промежуточное программное обеспечение и управлять CORS своими собственными средствами, вам просто нужно удалить все разрешенные источники (включая
*
) из Блейда настроек CORS на портале. Тогда вы можете использовать веб.config или Web Api для более конкретной обработки. Смотрите документацию:Не пытайтесь использовать как Web API CORS, так и App Service CORS в одном приложении API. Апп Сервисные CORS будут иметь приоритет, а Web API CORS не будет иметь никакого эффекта. Например, если включить один исходный домен в Службе приложений и включить все исходные домены в коде веб-API, приложение API Azure будет принимать вызовы только из домена, указанного в Azure.
См. также этот связанный вопрос :
Таким образом, окончательный ответ таков: Если ваше приложение не нуждается в очень специфическом управлении CORS, вы можете использовать службу приложений Azure CORS. В противном случае вам придется справьтесь с этим самостоятельно и отключите все настройки CORS в веб-приложении.
В конце концов я пошел более простым путем-удалил всю обработку кода
CORS
и просто поместил заголовки вweb.config
:<configuration> <system.webServer> <httpProtocol> <customHeaders> <add name="Access-Control-Allow-Origin" value="http://my-client-website.azurewebsites.net" /> <add name="Access-Control-Allow-Methods" value="*" /> <add name="Access-Control-Allow-Headers" value="accept, content-type, x-my-custom-header" /> <add name="Access-Control-Allow-Credentials" value="true" /> </customHeaders> </httpProtocol> ...
(Обратите внимание, что allow-origin не имеет косой черты в конце url-адреса!)
Разрешающая часть должна была удовлетворить SignalR, вероятно, он мог бы обойтись без нее.
Если кто-то найдет причину, почему кодированный способ не работает, я хотел бы знать!
Я тоже сталкивался с этой проблемой. Я думаю, что наконец-то получил программный WebAPI CORS, работающий в Службе приложений Azure с помощью этой волшебной комбинации изменений обработчика:
<remove name="OPTIONSVerbHandler" /> <remove name="ExtensionlessUrlHandler-Integrated-4.0" /> <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,POST,PUT,DELETE,HEAD,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
Вам действительно нужно удалить OPTIONSVerbHandler, чтобы избавиться от ответов перед полетом по умолчанию-с помощью пользовательских заголовков в интернете.config, вы просто нашли другой способ гарантировать, что эти заголовки будут записаны в те запросы опций, которые никогда не достигнут вашего приложения.
Ключ в том, чтобы убедиться, что что-то else отвечает за запросы опций, и я считаю, что это достигается путем повторного добавления ExtensionlessUrlHandler, указывающего опции в списке глаголов. Я не очень хорошо разбираюсь в IIS, поэтому я размышляю о механизме, но он, кажется, работает. Чистки рядов, это со мной крутится функциональность ПДБС веб-API в файл App_Start/WebApiConfig.cs вот так:
config.EnableCors(new MyCorsPolicyProvider());
Где
MyCorsPolicyProvider
- класс, реализующийICorsPolicyProvider
.