[Angular Execute Error] Access to XMLHttpRequest at 'http://XXX' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is

[Angular Execute Error] Access to XMLHttpRequest at 'http://XXX' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.


環境

Angular (version 5.2.6) (http://localhost:4200) 使用 HttpClientModule http.get().subscript() 連線至 http://localhost:57457/ 某 ASP.NET Handler (.ashx) 取得 JSON string 資料

解決方法 (共 3 步驟)

1. 把 Access-Control-Allow-Origin 設為 *   

保哥提到的 Google Chrome 擴充套件: [Allow CORS: Access-Control-Allow-origin] 與 [CORS Unblock]  擇一

加了之後還是錯誤:

GET http://localhost:57457/XXX.ashx 401 (Unauthorized)

2. 在 request Header 加 { withCredentials: true } ( 代表使用 Windows 驗證 )

拜讀CK大大文章,他有提到 Windows Authentication 加上 CORS 之後的狀況,有稍微講解。

我依樣畫葫蘆,先加  { withCredentials: true } ,但 API 部分,我用 VB.NET web form ,不是用 ASP.NET Core ,不曉得怎麼改。

Angular 程式碼如下:

this.http.get(url, { withCredentials: true}).subscribe(
  result => {
    this.data = JSON.parse(result['_body']);
  }
);

還是不行,錯誤如下:

Access to XMLHttpRequest at 'http://XXX/XXX.ashx' from origin 'http://localhost:4200' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.看來是不需要使用 Google Chrome 擴充套件,且已不是Angular 本身要改,而是 ASP.NET 網站要改。

3. 更改 global.asax.cs ,在Application_AuthenticateRequest() 內加 Response Header

我又進入上網爬文爬到死模式... 看到 RIP Tutorial 網站提到解法

我有稍微修改一下條件 ( HttpMethod = GET ),並省去 response.end() ,如下:

protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
    if (Context.Request.HttpMethod == "GET")
    {
        if (Context.Request.Headers["Origin"] != null)
            Context.Response.AddHeader("Access-Control-Allow-Origin", Context.Request.Headers["Origin"]);

        Context.Response.AddHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, MaxDataServiceVersion");
        Context.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        Context.Response.AddHeader("Access-Control-Allow-Credentials", "true");

        'Response.End();
    }
}

結果竟然成功了!

附註:

看了 [小喵分享文章],web.config 設定 header [Access-Control-Allow-Origin] 如下:

<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="http://localhost:4200"/>
  </customHeaders>
</httpProtocol>

程式碼中,以下這段就可以取代了,所以可以把小喵的那段拿掉:

Context.Response.AddHeader("Access-Control-Allow-Origin", Context.Request.Headers["Origin"]);

以上