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

 

 

 

×
Stay Informed

When you subscribe to the blog, we will send you an e-mail when there are new updates on the site so you wouldn't miss them.

React Suspense
Ansible 初體驗 (安裝 Docker)

相關文章

Comment for this post has been locked by admin.
 

評論