啟用 ASP.NET Web API 2 中的跨原始來源要求Enable cross-origin requests in ASP.NET Web API 2

藉由Mike Wassonby Mike Wasson

瀏覽器安全性可防止網頁對另一個網域提出 AJAX 要求。Browser security prevents a web page from making AJAX requests to another domain. 這項限制稱為同源原則,可防止惡意網站從另一個網站讀取敏感性資料。This restriction is called the same-origin policy, and prevents a malicious site from reading sensitive data from another site. 不過,有時候您可能想要讓呼叫您的 web API 的其他站台。However, sometimes you might want to let other sites call your web API.

跨原始資源共用(CORS) 是 W3C 標準,可讓伺服器放寬同源原則。Cross Origin Resource Sharing (CORS) is a W3C standard that allows a server to relax the same-origin policy. 使用 CORS,伺服器可以明確允許某些跨源要求並拒絕其他。Using CORS, a server can explicitly allow some cross-origin requests while rejecting others. CORS 可較為安全且更有彈性,比早期技術這類JSONPCORS is safer and more flexible than earlier techniques such as JSONP. 本教學課程會示範如何在您的 Web API 應用程式中啟用 CORS。This tutorial shows how to enable CORS in your Web API application.

在本教學課程中使用的軟體Software used in the tutorial

簡介Introduction

本教學課程會示範在 ASP.NET Web API 的 CORS 支援。This tutorial demonstrates CORS support in ASP.NET Web API. 我們先建立兩個 ASP.NET 專案 – 一個稱為 「 web 服務 」,裝載的 Web API 控制器和其他呼叫 「 WebClient 」,它會呼叫 web 服務。We'll start by creating two ASP.NET projects – one called "WebService", which hosts a Web API controller, and the other called "WebClient", which calls WebService. 因為兩個應用程式裝載在不同網域時,web 服務的 AJAX 要求從 WebClient 會是跨原始來源要求。Because the two applications are hosted at different domains, an AJAX request from WebClient to WebService is a cross-origin request.

什麼是 「 相同原始 」?What is "same origin"?

如果它們有相同的配置、 主機和連接埠,兩個 Url 會有相同的原點。Two URLs have the same origin if they have identical schemes, hosts, and ports. (RFC 6454)(RFC 6454)

這兩個 Url 有相同的來源:These two URLs have the same origin:

  • http://example.com/foo.html
  • http://example.com/bar.html

這些 Url 會有兩個不同的來源,比上一個:These URLs have different origins than the previous two:

  • http://example.net -不同的網域http://example.net - Different domain
  • http://example.com:9000/foo.html -不同的連接埠http://example.com:9000/foo.html - Different port
  • https://example.com/foo.html -不同的配置https://example.com/foo.html - Different scheme
  • http://www.example.com/foo.html -不同的子網域http://www.example.com/foo.html - Different subdomain

Note

Internet Explorer 在比較來源時,不會考慮該連接埠。Internet Explorer does not consider the port when comparing origins.

建立 web 服務專案Create the WebService project

Note

本節假設您已經知道如何建立 Web API 專案。This section assumes you already know how to create Web API projects. 如果沒有,請參閱Getting Started with ASP.NET Web APIIf not, see Getting Started with ASP.NET Web API.

  1. 啟動 Visual Studio 並建立新ASP.NET Web 應用程式 (.NET Framework) 專案。Start Visual Studio and create a new ASP.NET Web Application (.NET Framework) project.

  2. 新的 ASP.NET Web 應用程式對話方塊中,選取空白專案範本。In the New ASP.NET Web Application dialog box, select the Empty project template. 底下新增的資料夾和核心參考,選取Web API核取方塊。Under Add folders and core references for, select the Web API checkbox.

    Visual Studio 中的新 ASP.NET 專案對話方塊

  3. 新增名為 Web API 控制器TestController為下列程式碼:Add a Web API controller named TestController with the following code:

    using System.Net.Http;
    using System.Web.Http;
    
    namespace WebService.Controllers
    {
        public class TestController : ApiController
        {
            public HttpResponseMessage Get()
            {
                return new HttpResponseMessage()
                {
                    Content = new StringContent("GET: Test message")
                };
            }
    
            public HttpResponseMessage Post()
            {
                return new HttpResponseMessage()
                {
                    Content = new StringContent("POST: Test message")
                };
            }
    
            public HttpResponseMessage Put()
            {
                return new HttpResponseMessage()
                {
                    Content = new StringContent("PUT: Test message")
                };
            }
        }
    }
    
  4. 您可以在本機執行應用程式,或部署至 Azure。You can run the application locally or deploy to Azure. (在本教學課程的螢幕擷取畫面,應用程式會部署至 Azure App Service Web Apps。)若要確認 web API 會正常運作,巡覽至http://hostname/api/test/,其中hostname是您用來部署應用程式的網域。(For the screenshots in this tutorial, the app deploys to Azure App Service Web Apps.) To verify that the web API is working, navigate to http://hostname/api/test/, where hostname is the domain where you deployed the application. 您應該會看到回應文字,"取得:測試訊息"。You should see the response text, "GET: Test Message".

    Web 瀏覽器顯示測試訊息

建立 WebClient 專案Create the WebClient project

  1. 建立另一個ASP.NET Web 應用程式 (.NET Framework) 專案,然後選取MVC專案範本。Create another ASP.NET Web Application (.NET Framework) project and select the MVC project template. (選擇性) 選取變更驗證 > 不需要驗證Optionally, select Change Authentication > No Authentication. 本教學課程中,您不需要驗證。You don't need authentication for this tutorial.

    在 Visual Studio 中的 [新增 ASP.NET 專案] 對話方塊中的 MVC 範本

  2. 方案總管,開啟的檔案Views/Home/Index.cshtmlIn Solution Explorer, open the file Views/Home/Index.cshtml. 您可以將此檔案中的程式碼取代為下列:Replace the code in this file with the following:

    <div>
        <select id="method">
            <option value="get">GET</option>
            <option value="post">POST</option>
            <option value="put">PUT</option>
        </select>
        <input type="button" value="Try it" onclick="sendRequest()" />
        <span id='value1'>(Result)</span>
    </div>
    
    @section scripts {
    <script>
        // TODO: Replace with the URL of your WebService app
        var serviceUrl = 'http://mywebservice/api/test'; 
    
        function sendRequest() {
            var method = $('#method').val();
    
            $.ajax({
                type: method,
                url: serviceUrl
            }).done(function (data) {
                $('#value1').text(data);
            }).fail(function (jqXHR, textStatus, errorThrown) {
                $('#value1').text(jqXHR.responseText || textStatus);
            });
        }
    </script>
    }
    

    針對serviceUrl變數中,使用 web 服務應用程式的 URI。For the serviceUrl variable, use the URI of the WebService app.

  3. 在本機執行 WebClient 應用程式,或將它發佈至另一個網站。Run the WebClient app locally or publish it to another website.

當您按一下 試試看 」 按鈕時,AJAX 要求提交至 web 服務應用程式使用中列出的 HTTP 方法 (GET、 POST 或 PUT) 的下拉式清單方塊。When you click the "Try It" button, an AJAX request is submitted to the WebService app using the HTTP method listed in the dropdown box (GET, POST, or PUT). 這可讓您檢查不同的跨原始來源要求。This lets you examine different cross-origin requests. 目前,web 服務應用程式不支援 CORS,因此如果您按一下按鈕,您就會收到錯誤。Currently, the WebService app does not support CORS, so if you click the button you'll get an error.

在瀏覽器中的 'Try' 時發生錯誤

Note

如果您觀察在工具中的 HTTP 流量要Fiddler,您會看到瀏覽器會傳送 GET 要求,並要求成功,但 AJAX 呼叫會傳回錯誤。If you watch the HTTP traffic in a tool like Fiddler, you'll see that the browser does send the GET request, and the request succeeds, but the AJAX call returns an error. 請務必了解同源原則不會防止從瀏覽器傳送要求。It's important to understand that same-origin policy does not prevent the browser from sending the request. 相反地,它會防止應用程式看到回應Instead, it prevents the application from seeing the response.

Fiddler web 偵錯工具顯示 web 要求

啟用 CORSEnable CORS

現在讓我們的 web 服務應用程式中啟用 CORS。Now let's enable CORS in the WebService app. 首先,新增 CORS NuGet 套件。First, add the CORS NuGet package. 在 Visual Studio 中,從工具功能表上,選取NuGet 套件管理員,然後選取Package Manager ConsoleIn Visual Studio, from the Tools menu, select NuGet Package Manager, then select Package Manager Console. 在 [套件管理員主控台] 視窗中,輸入下列命令:In the Package Manager Console window, type the following command:

Install-Package Microsoft.AspNet.WebApi.Cors

此命令會安裝最新的封裝,並更新所有相依性,包括 core Web API 程式庫。This command installs the latest package and updates all dependencies, including the core Web API libraries. 使用-Version特定版本為目標的旗標。Use the -Version flag to target a specific version. CORS 封裝則需要 Web API 2.0 或更新版本。The CORS package requires Web API 2.0 or later.

開啟檔案應用程式_Start/WebApiConfig.csOpen the file App_Start/WebApiConfig.cs. 將下列程式碼加入WebApiConfig.Register方法:Add the following code to the WebApiConfig.Register method:

using System.Web.Http;
namespace WebService
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // New code
            config.EnableCors();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }
}

接下來,新增 [EnableCors] 屬性設定為TestController類別:Next, add the [EnableCors] attribute to the TestController class:

using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Cors;

namespace WebService.Controllers
{
    [EnableCors(origins: "http://mywebclient.azurewebsites.net", headers: "*", methods: "*")]
    public class TestController : ApiController
    {
        // Controller methods not shown...
    }
}

針對origins參數,使用 WebClient 應用程式的部署位置的 URI。For the origins parameter, use the URI where you deployed the WebClient application. 這讓跨源要求 WebClient,同時仍然不允許所有其他的跨網域要求。This allows cross-origin requests from WebClient, while still disallowing all other cross-domain requests. 稍後,我將說明的參數 [EnableCors] 中更多詳細資料。Later, I'll describe the parameters for [EnableCors] in more detail.

不包含結尾斜線origins URL。Do not include a forward slash at the end of the origins URL.

重新部署更新的 web 服務應用程式。Redeploy the updated WebService application. 您不需要更新 WebClient。You don't need to update WebClient. 現在應該會成功從 WebClient 的 AJAX 要求。Now the AJAX request from WebClient should succeed. 所有允許的 GET、 PUT 和 POST 方法。The GET, PUT, and POST methods are all allowed.

Web 瀏覽器顯示成功的測試訊息

CORS 的運作方式How CORS Works

本章節描述 CORS 要求,在 HTTP 訊息的層級中發生的動作。This section describes what happens in a CORS request, at the level of the HTTP messages. 請務必了解 CORS 的運作方式,以便您可以設定 [EnableCors] 正確屬性,並進行疑難排解,如果無法運作如預期般。It's important to understand how CORS works, so that you can configure the [EnableCors] attribute correctly and troubleshoot if things don't work as you expect.

CORS 規格引進了數個新的 HTTP 標頭啟用跨源要求。The CORS specification introduces several new HTTP headers that enable cross-origin requests. 如果瀏覽器支援 CORS,它會設定自動跨原始來源要求,這些標頭您不需要執行任何 JavaScript 程式碼中的特殊動作。If a browser supports CORS, it sets these headers automatically for cross-origin requests; you don't need to do anything special in your JavaScript code.

以下是跨原始要求的範例。Here is an example of a cross-origin request. 「 來源 」 標頭會提供提出要求的站台的網域。The "Origin" header gives the domain of the site that is making the request.

GET http://myservice.azurewebsites.net/api/test HTTP/1.1
Referer: http://myclient.azurewebsites.net/
Accept: */*
Accept-Language: en-US
Origin: http://myclient.azurewebsites.net
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)
Host: myservice.azurewebsites.net

如果伺服器允許的要求,它會設定存取控制-允許-原始標頭。If the server allows the request, it sets the Access-Control-Allow-Origin header. 此標頭的值符合 Origin 標頭,或者是萬用字元值"*",表示允許任何來源。The value of this header either matches the Origin header, or is the wildcard value "*", meaning that any origin is allowed.

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: text/plain; charset=utf-8
Access-Control-Allow-Origin: http://myclient.azurewebsites.net
Date: Wed, 05 Jun 2013 06:27:30 GMT
Content-Length: 17

GET: Test message

如果回應不包含存取控制-允許-原始標頭,AJAX 要求將會失敗。If the response does not include the Access-Control-Allow-Origin header, the AJAX request fails. 具體而言,瀏覽器不允許要求。Specifically, the browser disallows the request. 即使伺服器會傳回成功的回應,瀏覽器不會回應提供用戶端應用程式。Even if the server returns a successful response, the browser does not make the response available to the client application.

預檢要求Preflight Requests

對於某些 CORS 要求,瀏覽器會傳送其他要求,稱為 「 預檢要求,」 後才會傳送實際要求的資源。For some CORS requests, the browser sends an additional request, called a "preflight request", before it sends the actual request for the resource.

如果下列條件成立,則瀏覽器可以略過預檢要求:The browser can skip the preflight request if the following conditions are true:

  • 要求方法是 GET、 HEAD 或 POSTThe request method is GET, HEAD, or POST, and

  • 應用程式不會設定 Accept、 Accept-language、 內容語言、 以外任何要求標頭內容類型或最後一個事件識別碼、The application does not set any request headers other than Accept, Accept-Language, Content-Language, Content-Type, or Last-Event-ID, and

  • Content-type 標頭 (如果設定) 是下列其中之一:The Content-Type header (if set) is one of the following:

    • application/x-www-form-urlencodedapplication/x-www-form-urlencoded
    • multipart/form-datamultipart/form-data
    • text/plaintext/plain

要求標頭的相關規則有套用到應用程式設定所呼叫的標頭setRequestHeaderXMLHttpRequest物件。The rule about request headers applies to headers that the application sets by calling setRequestHeader on the XMLHttpRequest object. (CORS 規格會呼叫這些 「 作者要求標頭 」)。規則不適用於標頭瀏覽器設定,例如使用者代理程式、 主機或內容長度。(The CORS specification calls these "author request headers".) The rule does not apply to headers the browser can set, such as User-Agent, Host, or Content-Length.

預檢要求的範例如下:Here is an example of a preflight request:

OPTIONS http://myservice.azurewebsites.net/api/test HTTP/1.1
Accept: */*
Origin: http://myclient.azurewebsites.net
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: accept, x-my-custom-header
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)
Host: myservice.azurewebsites.net
Content-Length: 0

事前要求使用 HTTP OPTIONS; 方法。The pre-flight request uses the HTTP OPTIONS method. 它包含兩個特殊標頭:It includes two special headers:

  • 存取控制-要求的方法:將會用於實際要求的 HTTP 方法。Access-Control-Request-Method: The HTTP method that will be used for the actual request.
  • 存取控制-access-control-request-headers 標:要求標頭的清單,應用程式實際要求上設定。Access-Control-Request-Headers: A list of request headers that the application set on the actual request. (同樣地,這不包括瀏覽器設定的標頭。)(Again, this does not include headers that the browser sets.)

以下是範例回應,假設伺服器允許的要求:Here is an example response, assuming that the server allows the request:

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 0
Access-Control-Allow-Origin: http://myclient.azurewebsites.net
Access-Control-Allow-Headers: x-my-custom-header
Access-Control-Allow-Methods: PUT
Date: Wed, 05 Jun 2013 06:33:22 GMT

此回應包含存取控制-允許-方法標頭,其中列出允許的方法,並選擇性地存取控制-允許-標頭的標頭,它會列出允許的標頭。The response includes an Access-Control-Allow-Methods header that lists the allowed methods, and optionally an Access-Control-Allow-Headers header, which lists the allowed headers. 如果預檢要求成功,瀏覽器會傳送實際要求,如先前所述。If the preflight request succeeds, the browser sends the actual request, as described earlier.

工具通常用來測試與預檢 OPTIONS 要求的端點 (例如FiddlerPostman) 不要傳送必要的 「 選項 」 標頭,根據預設。Tools commonly used to test endpoints with preflight OPTIONS requests (for example, Fiddler and Postman) don't send the required OPTIONS headers by default. 確認Access-Control-Request-MethodAccess-Control-Request-Headers與要求一起傳送的標頭和選項的標頭達到透過 IIS 應用程式。Confirm that the Access-Control-Request-Method and Access-Control-Request-Headers headers are sent with the request and that OPTIONS headers reach the app through IIS.

若要設定 IIS 以允許 ASP.NET 應用程式來接收和處理選項要求,請將下列組態新增至應用程式的web.config檔案中<system.webServer><handlers>區段:To configure IIS to allow an ASP.NET app to receive and handle OPTION requests, add the following configuration to the app's web.config file in the <system.webServer><handlers> section:

<system.webServer>
  <handlers>
    <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
    <remove name="OPTIONSVerbHandler" />
    <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
  </handlers>
</system.webServer>

移除OPTIONSVerbHandler防止 IIS 處理選項要求。The removal of OPTIONSVerbHandler prevents IIS from handling OPTIONS requests. 取代為ExtensionlessUrlHandler-Integrated-4.0允許連到應用程式,因為預設模組登錄只允許使用無副檔名 Url 的 GET、 HEAD、 POST 和偵錯要求的 OPTIONS 要求。The replacement of ExtensionlessUrlHandler-Integrated-4.0 allows OPTIONS requests to reach the app because the default module registration only allows GET, HEAD, POST, and DEBUG requests with extensionless URLs.

[EnableCors] 的範圍規則Scope Rules for [EnableCors]

您可以在應用程式中,每個動作,每個控制站,或適用於所有的 Web API 控制器啟用 CORS。You can enable CORS per action, per controller, or globally for all Web API controllers in your application.

每個動作Per Action

若要啟用 CORS 的單一動作時,將 [EnableCors] 動作方法上的屬性。To enable CORS for a single action, set the [EnableCors] attribute on the action method. 下列範例會啟用 CORSGetItem僅方法。The following example enables CORS for the GetItem method only.

public class ItemsController : ApiController
{
    public HttpResponseMessage GetAll() { ... }

    [EnableCors(origins: "http://www.example.com", headers: "*", methods: "*")]
    public HttpResponseMessage GetItem(int id) { ... }

    public HttpResponseMessage Post() { ... }
    public HttpResponseMessage PutItem(int id) { ... }
}

每個控制站Per Controller

如果您設定 [EnableCors] 在控制器類別,它適用於控制站上的所有動作。If you set [EnableCors] on the controller class, it applies to all the actions on the controller. 若要停用動作的 CORS,請新增 [DisableCors] 屬性的動作。To disable CORS for an action, add the [DisableCors] attribute to the action. 下列範例會針對每個方法,除了啟用 CORS PutItemThe following example enables CORS for every method except PutItem.

[EnableCors(origins: "http://www.example.com", headers: "*", methods: "*")]
public class ItemsController : ApiController
{
    public HttpResponseMessage GetAll() { ... }
    public HttpResponseMessage GetItem(int id) { ... }
    public HttpResponseMessage Post() { ... }

    [DisableCors]
    public HttpResponseMessage PutItem(int id) { ... }
}

全域Globally

若要啟用 CORS 的應用程式中的所有 Web API 控制器時,傳遞EnableCorsAttribute執行個體EnableCors方法:To enable CORS for all Web API controllers in your application, pass an EnableCorsAttribute instance to the EnableCors method:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        var cors = new EnableCorsAttribute("www.example.com", "*", "*");
        config.EnableCors(cors);
        // ...
    }
}

如果您在一個以上的範圍設定的屬性,優先順序就會是:If you set the attribute at more than one scope, the order of precedence is:

  1. 動作Action
  2. 控制器Controller
  3. GlobalGlobal

設定允許的來源Set the allowed origins

Origins的參數 [EnableCors] 屬性會指定哪些原始來源允許存取資源。The origins parameter of the [EnableCors] attribute specifies which origins are allowed to access the resource. 值是允許的來源的逗號分隔清單。The value is a comma-separated list of the allowed origins.

[EnableCors(origins: "http://www.contoso.com,http://www.example.com", 
    headers: "*", methods: "*")]

您也可以使用萬用字元值"*」 以允許來自任何來源的要求。You can also use the wildcard value "*" to allow requests from any origins.

請仔細考慮,才能允許來自任何來源的要求。Consider carefully before allowing requests from any origin. 這表示幾乎任何網站可以讓您的 web API 的 AJAX 呼叫。It means that literally any website can make AJAX calls to your web API.

// Allow CORS for all origins. (Caution!)
[EnableCors(origins: "*", headers: "*", methods: "*")]

設定允許的 HTTP 方法Set the allowed HTTP methods

方法的參數 [EnableCors] 屬性會指定哪些 HTTP 方法才能存取資源。The methods parameter of the [EnableCors] attribute specifies which HTTP methods are allowed to access the resource. 若要允許所有方法,使用萬用字元值"*」。To allow all methods, use the wildcard value "*". 下列範例允許只有 GET 和 POST 要求。The following example allows only GET and POST requests.

[EnableCors(origins: "http://www.example.com", headers: "*", methods: "get,post")]
public class TestController : ApiController
{
    public HttpResponseMessage Get() { ... }
    public HttpResponseMessage Post() { ... }
    public HttpResponseMessage Put() { ... }    
}

設定允許的要求標頭Set the allowed request headers

這篇文章所述稍早如何預檢要求可能會包含存取控制-access-control-request-headers 標標頭,列出應用程式設定的 HTTP 標頭 (所謂 「 撰寫要求標頭 」)。This article described earlier how a preflight request might include an Access-Control-Request-Headers header, listing the HTTP headers set by the application (the so-called "author request headers"). 標頭的參數 [EnableCors] 屬性可讓您指定允許哪些作者要求標頭。The headers parameter of the [EnableCors] attribute specifies which author request headers are allowed. 若要允許任何標頭,設定標頭到 「*"。To allow any headers, set headers to "*". 允許清單特定的標頭,設定標頭允許的標頭以逗號分隔清單:To whitelist specific headers, set headers to a comma-separated list of the allowed headers:

[EnableCors(origins: "http://example.com", 
    headers: "accept,content-type,origin,x-my-header", methods: "*")]

不過,瀏覽器並不會在它們如何設定存取控制-access-control-request-headers 標完全一致。However, browsers are not entirely consistent in how they set Access-Control-Request-Headers. 例如,Chrome 目前包含 「 來源 」。For example, Chrome currently includes "origin". FireFox 不包含標準標頭,例如"Accept",即使應用程式會設定它們的指令碼中。FireFox does not include standard headers such as "Accept", even when the application sets them in script.

如果您設定標頭到以外的任何項目"*」,您應該至少包含在 「 accept 」,"content-type"、"origin",以及您想要支援的任何自訂標頭。If you set headers to anything other than "*", you should include at least "accept", "content-type", and "origin", plus any custom headers that you want to support.

設定允許的回應標頭Set the allowed response headers

根據預設,瀏覽器不會公開所有應用程式的回應標頭。By default, the browser does not expose all of the response headers to the application. 是預設可用的回應標頭如下:The response headers that are available by default are:

  • Cache-ControlCache-Control
  • 內容語言Content-Language
  • Content-TypeContent-Type
  • ExpiresExpires
  • Last-ModifiedLast-Modified
  • PragmaPragma

CORS 規格會呼叫這些簡單的回應標頭The CORS spec calls these simple response headers. 若要讓其他標頭可供應用程式,設定exposedHeaders的參數 [EnableCors]To make other headers available to the application, set the exposedHeaders parameter of [EnableCors].

在下列範例中,控制器的Get方法會設定名為 'X 自訂-標頭' 的自訂標頭。In the following example, the controller's Get method sets a custom header named ‘X-Custom-Header'. 根據預設,瀏覽器不會公開此標頭中的跨原始來源要求。By default, the browser will not expose this header in a cross-origin request. 要使用的標頭,請納入 ' X-自訂-Header exposedHeadersTo make the header available, include ‘X-Custom-Header' in exposedHeaders.

[EnableCors(origins: "*", headers: "*", methods: "*", exposedHeaders: "X-Custom-Header")]
public class TestController : ApiController
{
    public HttpResponseMessage Get()
    {
        var resp = new HttpResponseMessage()
        {
            Content = new StringContent("GET: Test message")
        };
        resp.Headers.Add("X-Custom-Header", "hello");
        return resp;
    }
}

在跨原始來源要求中傳遞認證Pass credentials in cross-origin requests

認證需要在 CORS 要求的特殊處理。Credentials require special handling in a CORS request. 根據預設,瀏覽器不會傳送任何與跨原始要求的認證。By default, the browser does not send any credentials with a cross-origin request. 認證包含 cookie,以及 HTTP 驗證配置。Credentials include cookies as well as HTTP authentication schemes. 若要傳送與跨原始要求的認證,用戶端必須將XMLHttpRequest.withCredentials設為 true。To send credentials with a cross-origin request, the client must set XMLHttpRequest.withCredentials to true.

使用XMLHttpRequest直接:Using XMLHttpRequest directly:

var xhr = new XMLHttpRequest();
xhr.open('get', 'http://www.example.com/api/test');
xhr.withCredentials = true;

在 jQuery 中:In jQuery:

$.ajax({
    type: 'get',
    url: 'http://www.example.com/api/test',
    xhrFields: {
        withCredentials: true
    }

此外,伺服器必須允許的認證。In addition, the server must allow the credentials. 若要在 Web API 中,允許跨原始來源的認證,請設定SupportsCredentials屬性設為 true,在 [EnableCors] 屬性:To allow cross-origin credentials in Web API, set the SupportsCredentials property to true on the [EnableCors] attribute:

[EnableCors(origins: "http://myclient.azurewebsites.net", headers: "*", 
    methods: "*", SupportsCredentials = true)]

如果這個屬性為 true,則 HTTP 回應將包含存取控制-允許-認證標頭。If this property is true, the HTTP response will include an Access-Control-Allow-Credentials header. 此標頭會告知瀏覽器伺服器允許跨原始來源要求認證。This header tells the browser that the server allows credentials for a cross-origin request.

如果瀏覽器傳送認證,但回應不包含有效的存取控制-允許-認證標頭,瀏覽器不會公開應用程式、 回應和 AJAX 要求失敗。If the browser sends credentials, but the response does not include a valid Access-Control-Allow-Credentials header, the browser will not expose the response to the application, and the AJAX request fails.

設定請小心SupportsCredentials為 true,因為這表示在另一個定義域的網站可以傳送給您的 Web API,代替使用者的登入的使用者的認證不會察覺使用者。Be careful about setting SupportsCredentials to true, because it means a website at another domain can send a logged-in user's credentials to your Web API on the user's behalf, without the user being aware. CORS 規格也會指出該設定origins要" * "無效如果SupportsCredentials為 true。The CORS spec also states that setting origins to "*" is invalid if SupportsCredentials is true.

自訂的 CORS 原則提供者Custom CORS policy providers

[EnableCors] 屬性會實作ICorsPolicyProvider介面。The [EnableCors] attribute implements the ICorsPolicyProvider interface. 您可以提供您自己的實作方式是建立衍生自類別屬性,並會實作ICorsPolicyProviderYou can provide your own implementation by creating a class that derives from Attribute and implements ICorsPolicyProvider.

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)]
public class MyCorsPolicyAttribute : Attribute, ICorsPolicyProvider 
{
    private CorsPolicy _policy;

    public MyCorsPolicyAttribute()
    {
        // Create a CORS policy.
        _policy = new CorsPolicy
        {
            AllowAnyMethod = true,
            AllowAnyHeader = true
        };

        // Add allowed origins.
        _policy.Origins.Add("http://myclient.azurewebsites.net");
        _policy.Origins.Add("http://www.contoso.com");
    }

    public Task<CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request)
    {
        return Task.FromResult(_policy);
    }
}

現在您可以套用的屬性的任何放置,您會放置 [EnableCors]Now you can apply the attribute any place that you would put [EnableCors].

[MyCorsPolicy]
public class TestController : ApiController
{
    .. //

例如,自訂的 CORS 原則提供者無法從組態檔讀取設定。For example, a custom CORS policy provider could read the settings from a configuration file.

您可以使用屬性的替代方案,以註冊ICorsPolicyProviderFactory建立的物件ICorsPolicyProvider物件。As an alternative to using attributes, you can register an ICorsPolicyProviderFactory object that creates ICorsPolicyProvider objects.

public class CorsPolicyFactory : ICorsPolicyProviderFactory
{
    ICorsPolicyProvider _provider = new MyCorsPolicyProvider();

    public ICorsPolicyProvider GetCorsPolicyProvider(HttpRequestMessage request)
    {
        return _provider;
    }
}

若要設定ICorsPolicyProviderFactory,呼叫SetCorsPolicyProviderFactory擴充方法,在啟動時,如下所示:To set the ICorsPolicyProviderFactory, call the SetCorsPolicyProviderFactory extension method at startup, as follows:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.SetCorsPolicyProviderFactory(new CorsPolicyFactory());
        config.EnableCors();

        // ...
    }
}

瀏覽器支援Browser support

Web API CORS 套件是一種伺服器端技術。The Web API CORS package is a server-side technology. 使用者的瀏覽器也必須支援 CORS。The user's browser also needs to support CORS. 幸運的是,所有主要瀏覽器的目前版本包括cors 支援Fortunately, the current versions of all major browsers include support for CORS.