簡體   English   中英

部署在Azure Web App / Azure API上時缺少CORS標頭

[英]CORS headers missing when deployed on Azure Web App / Azure API

我創建了一個OWIN托管的WebAPI 2 還有一個Web應用程序( AngularJS ),它使用API​​並充當客戶端。

我已經將必要的CORS代碼添加到Startup.cs ,並在不同於客戶端的端口上將其托管在本地IIS中,並確認它修復了Cors問題。

然后,我將這兩個應用程序部署到Azure(我已將兩個應用程序都放在Azure上作為Web應用程序,我也嘗試將OWIN放到當前處於預覽狀態的Azure API中)但是 - 預檢請求現在失敗了(沒有Access-Control-Allow-Origin出現在響應中)。

問:我不知道Azure的某些特定內容嗎? 為什么OWIN在部署時沒有提供此標頭,但是它正在使用localhost? 我沒有在應用程序的Azure刀片設置的屬性窗口中看到任何約束。

筆記:

關於我正在使用的設置的一些細節:

  • 使用OwinWebAPI2NinjectSignalR
  • 自定義令牌在每個后續請求的標頭中發布和提供,並使用自定義過濾器進行驗證。
  • 我現在正在嘗試的是*

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<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中注釋掉以下行以支持OPTIONS HTTP請求(否則,它會拋出HTTP錯誤405)

<system.webServer>
   <handlers>
     <!--<remove name="OPTIONSVerbHandler" />-->
     ...

實際上,Azure網站應該為您管理CORS。 我想你錯過了一個方便的Azure網站刀片:

Azure網站CORS刀片

如果我們自己的理解是正確的,那么這個Azure中間件的問題就是允許您配置除允許的起源之外的任何內容。 它缺少“允許標頭”可管理配置,每URL規則和其他有用的CORS HTTP標頭。 更糟糕的是:它會在設置自己的每個HTTP響應之前丟棄所有與CORS相關的標頭,因此它甚至不能讓你處理它沒有的內容。

好處是您可以完全禁用此中間件並通過自己的方式管理CORS,您必須從門戶中的CORS設置刀片中刪除每個允許的來源(包括* )。 然后,您可以使用web.config或Web Api更具體地處理它。 查看文檔

不要嘗試在一個API應用程序中同時使用Web API CORS和App Service CORS。 App Service CORS優先,Web API CORS不起作用。 例如,如果在App Service中啟用一個源域,並在Web API代碼中啟用所有源域,則Azure API應用程序將僅接受來自您在Azure中指定的域的調用。

另見相關問題

因此,最終的答案是:如果您的應用程序不需要非常具體的CORS管理,則可以使用Azure App Service CORS。 否則,您需要自己處理它並禁用Web應用程序中的所有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的末尾沒有斜杠!)

allow-credentials部分是為了滿足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擺脫默認預檢響應-通過在web.config中使用自定義標題,你只是發現了另一種方式,以確保這些標題得到寫入這些選項要求,從來沒有達到你的應用程序。

關鍵是確保其他東西負責OPTIONS請求,我相信通過在動詞列表中重新添加指定OPTIONS的ExtensionlessUrlHandler來實現。 我不熟悉IIS,所以我猜測機制,但它似乎確實有效。 FWIW,這是我在App_Start / WebApiConfig.cs中調整WebAPI的CORS功能,如下所示:

config.EnableCors(new MyCorsPolicyProvider());

其中MyCorsPolicyProvider是一個實現ICorsPolicyProvider的類。

我在azure portal上設置了這個,但是對於跨域請求,chrome預檢仍然失敗。 在azure文檔中,預檢使用OPTION http動詞,我猜chrome可能只使用GET,因此沒有標題值。

我的問題是我不小心將http而不是https放入Azure AD B2C自定義頁面配置刀片......更改為https后,它就像一個魅力。

在AZURE雲shell上嘗試此命令

Azure雲外殼

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

**** 1 **** =您的資源組名稱

**** 2 **** =您的應用名稱

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM