選單
GSS 技術部落格
在這個園地裡我們將從技術、專案管理、客戶對談面和大家分享我們多年的經驗,希望大家不管是喜歡或是有意見,都可以回饋給我們,讓我們有機會和大家對話並一起成長!
若有任何問題請來信:gss_crm@gss.com.tw
3 分鐘閱讀時間 (695 個字)

ASP.NET Core Cross-Origin Resource Sharing(CORS)

sitting-and-typing-on-macbook-pro-mockup

前言

大家都知道,當某網頁透過 JS 要 Post 另一個網頁時,如果它們是不同 Domain 就會受到 Browser 的安全限制。
而在 ASP.NET 時,因為都 Host 在 IIS 上面,所以可以在 web.config 中去設定 CORS 的標頭。

如果是 ASP.NET Core 是否也相同呢?

研究

ASP.NET CORE + IIS (WEB.CONFIG)

當我們將 ASP.NET Core API 專案 Host 在 IIS 上時,再透過另個網域網頁去 POST 它時,就會出現以下的錯誤訊息,
Access to fetch at ‘http://localhost/rmstore/product' from origin ‘http://localhost:56070' has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. If an opaque response serves your needs, set the request’s mode to ‘no-cors’ to fetch the resource with CORS disabled.

這表示我們需要給它 CORS 相關的 Header ,所以在 web.config 中加入 Header 的設定,如下,

 

<?xml version="1.0" encoding="utf-8"?>
 <configuration> 
<location path="." inheritInChildApplications="false">
 <system.webServer>
 <handlers> 
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" >
</handlers>
 <aspNetCore processPath=".\RMStore.API.exe" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" />
 </system.webServer>
 </location>
 <system.webServer>
 <httpProtocol>
 <customHeaders> 
 <add name="Access-Control-Allow-Origin" value="*" /> 
 <add name="Access-Control-Allow-Headers" value="*" /> 
 <add name="Access-Control-Allow-Methods" value="*" /> 
 <add name="Access-Control-Allow-Credentials" value="true" /> 
 </customHeaders> </httpProtocol> </system.webServer> </configuration>

 

再測試網頁,這時出現另一個錯誤訊息,如下,

Access to fetch at ‘http://localhost/rmstore/product' from origin ‘http://localhost:56070' has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: It does not have HTTP ok status.

這表示 Browser 在做 prefight 時,回來的 stats 是不對的,所以就使用 Fiddler 試一下,果然是回 405 Method Not Allowed

 

可是在 Header 中已設定了 Access-Control-Allow-Methods 為 * 了。
所以應該是在 ASP.NET Core 程式中被擋住了,透過程式執行起來,再透過 Fiddler 跑 OPTIONS 也是回 405。
所以必需將預設的 CORS 設定 allow methods ,所以在 StartUp.cs 的 ConfigureServices Method 中,加入設定預設 CORS 的 Allow Methods 設定,

public void ConfigureServices(IServiceCollection services)
{
    // other codes....
    services.AddCors(options =>
    {
        options.AddDefaultPolicy(
            builder =>
            {
                builder.AllowAnyMethod();
            });
    });
}

在 StartUp.cs 的 Configure Method 中,使用 CORS,

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // other codes...
    app.UseCors();
    //
}

重新建置後,執行 OPTIONS 就會回 204 ,所以透過網頁來執行就沒問題了。

ASP.NET CORE

不過,即然都在程式中設定了,那就直接在程式中設定,而 Allow-Origin 則可以從 appsettings.json 中讀取,
appsettings.json

"Cors": {
    "AllowOrigin": "http://localhost:56070, https://localhost:44330"
}

或是 allow all

"Cors": {
    "AllowOrigin": "*"
}

而將相關的設定,寫在 StartUp.cs 的 ConfigureServices Method 中,

public void ConfigureServices(IServiceCollection services)
{
    // other code....
    string[] corsOrigins = Configuration["Cors:AllowOrigin"].Split(',', StringSplitOptions.RemoveEmptyEntrie    services.AddCors(options =>
    {
        options.AddDefaultPolicy(
            builder =>
            {
                if (corsOrigins.Contains("*"))
                {
                    builder.SetIsOriginAllowed(_ => true);
                }
                else
                {
                    builder.WithOrigins(corsOrigins);
                }
                builder.AllowAnyMethod();
                builder.AllowAnyHeader();
                builder.AllowCredentials();               
            });
    });
}

所以原本的 web.config 的 CORS 設定就可以移除了。
這樣就只要改 appsettings.json ,而且如果有多 Domain 的網頁要存取的話,ASP.NET Core 會依 Request 的來源動態傳回 Access-Control-Allow-Origin 的值。

參考資料

Enable Cross-Origin Requests (CORS) in ASP.NET Core
preflight request (OPTIONS) WebAPI 時,會回 405 Method Not Allowed ?
.NET Core how to add any origin to CORS and allow credentials

 

 

 

開展企業的 API 經濟規模前 請問你/企業準備好了嗎?
有效地使用 ASP.NET Core Logging - 1

相關文章