Asp.net

使用具有多個來源的 PUT 和 DELETE 請求時如何解決 ASP.NET Web API CORS Preflight 問題?

  • January 24, 2018

我有一個由三個不同的 SPA 呼叫的 ASP.NET Web API。我正在為 Web API 使用 Windows 身份驗證。我最初嘗試在 Web.config 中配置 CORS,如下所示:

<httpProtocol>
   &lt;customHeaders&gt;
       &lt;add name="Access-Control-Allow-Origin" value="http://localhost:63342" /&gt;
       &lt;add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE" /&gt;
       &lt;add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" /&gt;
       &lt;add name="Access-Control-Allow-Credentials" value="true" /&gt;
   &lt;/customHeaders&gt;
&lt;/httpProtocol&gt;

這導致了這個預檢問題:

Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin (...) is therefore not allowed access.

我通過在 Global.asax.cs 中添加以下方法解決了這個問題:

protected void Application_BeginRequest()
{
   if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
   {
       Response.Flush();
   }
}

這種方法非常適合單個 SPA。我想我可以去 Web.config 並像這樣添加其他來源:

&lt;add name="Access-Control-Allow-Origin" value="http://localhost:63342,http://localhost:63347,http://localhost:63345/&gt;

但顯然這是不允許的。這產生了以下錯誤:

The 'Access-Control-Allow-Origin' header contains multiple values (...), but only one is allowed. Origin (...) is therefore not allowed access.

因此,為了嘗試解決這個問題,我改變了方法,而是決定嘗試在 WebAPIConfig.cs 上配置 CORS,在 Register 方法中,如下所示:

var cors = new EnableCorsAttribute("http://localhost:63342,http://localhost:63347,http://localhost:63345", "Origin, X-Requested-With, Content-Type, Accept", "GET, POST, PUT, DELETE");
cors.SupportsCredentials = true;
config.EnableCors(cors);

我認為這會起作用,但現在我在使用 PUT 和 DELETE 請求時再次遇到預檢錯誤,我不知道如何解決這個問題。我調試了 Application_BeginRequest 方法,它仍在刷新 OPTIONS 請求,所以我不知道是什麼導致了這個錯誤。有誰知道我該如何解決這個問題?

編輯:

預檢錯誤的列印:

在此處輸入圖像描述

我能夠通過進一步自定義 Global.asax.cs 中的 Application_BeginRequest 方法來解決我的問題,如下所示:

protected void Application_BeginRequest()
{
   if (Request.HttpMethod == "OPTIONS")
   {
       Response.StatusCode = (int)HttpStatusCode.OK;
       Response.AppendHeader("Access-Control-Allow-Origin", Request.Headers.GetValues("Origin")[0]);
       Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
       Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
       Response.AppendHeader("Access-Control-Allow-Credentials", "true");
       Response.End();
   }
}

此程式碼所做的是將失去的標頭添加到導致預檢錯誤的 OPTIONS 響應(預檢請求)中。由於我有不同的來源呼叫我的 Web API,我使用Request.Headers.GetValues("Origin")[0])動態設置響應中的來源。

在 WebApiConfig.cs 中,我仍然指定了不同的來源,但在標頭和方法上使用了萬用字元,並將其設置SupportsCredentials為 true,如下所示:

var cors = new EnableCorsAttribute("http://localhost:63342,http://localhost:63347,http://localhost:63345", "*", "*");
cors.SupportsCredentials = true;
config.EnableCors(cors);

此外,如果您像我一樣使用 A​​ngularJS,則必須配置 $http 以使用憑據。這可以像這樣全域配置:

angular
.module('Application')
.config(['$httpProvider',
   function config($httpProvider) {
       $httpProvider.defaults.withCredentials = true;
   }
]);

就是這樣。這解決了我的問題。如果其他人仍有問題,我建議閱讀以下出版物,這有助於我找到答案:

引用自:https://stackoverflow.com/questions/39613831