Habilitar solicitações entre origens na API Web ASP.NET 2Enable cross-origin requests in ASP.NET Web API 2

por Mike Wassonby Mike Wasson

Segurança do navegador impede que uma página da web faça solicitações AJAX para outro domínio.Browser security prevents a web page from making AJAX requests to another domain. Essa restrição é chamada de política de mesma origeme impede que um site mal-intencionado lendo dados confidenciais de outro site.This restriction is called the same-origin policy, and prevents a malicious site from reading sensitive data from another site. No entanto, às vezes, talvez queira permitir que outros sites chamar sua API da web.However, sometimes you might want to let other sites call your web API.

Entre o compartilhamento de recursos de origem (CORS) é um padrão W3C que permite que um servidor relaxar a política de mesma origem.Cross Origin Resource Sharing (CORS) is a W3C standard that allows a server to relax the same-origin policy. Usando o CORS, um servidor pode explicitamente permitir algumas solicitações entre origens enquanto rejeita outras.Using CORS, a server can explicitly allow some cross-origin requests while rejecting others. O CORS é mais seguro e flexível que técnicas anteriores, como JSONP.CORS is safer and more flexible than earlier techniques such as JSONP. Este tutorial mostra como habilitar o CORS em seu aplicativo de API da Web.This tutorial shows how to enable CORS in your Web API application.

Software usado no tutorialSoftware used in the tutorial

IntroduçãoIntroduction

Este tutorial demonstra o que suporte a CORS na API Web ASP.NET.This tutorial demonstrates CORS support in ASP.NET Web API. Vamos começar criando dois projetos do ASP.NET – um chamado "serviço Web", que hospeda um controlador de API da Web, e outro chamado "WebClient", que chama o serviço 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. Porque os dois aplicativos hospedados em diferentes domínios, uma solicitação de AJAX do WebClient para o serviço Web é uma solicitação entre origens.Because the two applications are hosted at different domains, an AJAX request from WebClient to WebService is a cross-origin request.

O que é "mesma origem"?What is "same origin"?

Duas URLs têm a mesma origem se eles tiverem as portas, hosts e esquemas idênticas.Two URLs have the same origin if they have identical schemes, hosts, and ports. (RFC 6454)(RFC 6454)

Essas duas URLs têm a mesma origem:These two URLs have the same origin:

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

Essas URLs tem diferentes origens que o anterior dois:These URLs have different origins than the previous two:

  • http://example.net -Domínio diferentehttp://example.net - Different domain
  • http://example.com:9000/foo.html -Porta diferentehttp://example.com:9000/foo.html - Different port
  • https://example.com/foo.html -Esquema diferentehttps://example.com/foo.html - Different scheme
  • http://www.example.com/foo.html -Subdomínio diferentehttp://www.example.com/foo.html - Different subdomain

Note

Internet Explorer não considera a porta ao comparar as origens.Internet Explorer does not consider the port when comparing origins.

Criar o projeto WebServiceCreate the WebService project

Note

Esta seção pressupõe que você já sabe como criar projetos de API da Web.This section assumes you already know how to create Web API projects. Caso contrário, consulte Introdução ao ASP.NET Web API.If not, see Getting Started with ASP.NET Web API.

  1. Inicie o Visual Studio e crie um novo aplicativo Web ASP.NET (.NET Framework) projeto.Start Visual Studio and create a new ASP.NET Web Application (.NET Framework) project.

  2. No novo aplicativo Web ASP.NET caixa de diálogo, selecione o vazia modelo de projeto.In the New ASP.NET Web Application dialog box, select the Empty project template. Sob adicionar pastas e os principais referências para, selecione o API da Web caixa de seleção.Under Add folders and core references for, select the Web API checkbox.

    Novo diálogo de projeto do ASP.NET no Visual Studio

  3. Adicionar um controlador de API da Web chamado TestController com o código a seguir: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. Você pode executar o aplicativo localmente ou implantar no Azure.You can run the application locally or deploy to Azure. (Para as capturas de tela neste tutorial, o aplicativo é implantado para aplicativos de Web do serviço de aplicativo do Azure.) Para verificar se a API da web está funcionando, navegue até http://hostname/api/test/, onde hostname é o domínio onde você implantou o aplicativo.(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. Você deve ver o texto de resposta, "obter: Mensagem de teste".You should see the response text, "GET: Test Message".

    Mensagem de teste de mostrando de navegador da Web

Criar o projeto de WebClientCreate the WebClient project

  1. Criar outra aplicativo Web ASP.NET (.NET Framework) do projeto e selecione o MVC modelo de projeto.Create another ASP.NET Web Application (.NET Framework) project and select the MVC project template. Opcionalmente, selecione alterar autenticação > sem autenticação.Optionally, select Change Authentication > No Authentication. Autenticação não é necessário para este tutorial.You don't need authentication for this tutorial.

    Modelo MVC na caixa de diálogo Novo projeto ASP.NET no Visual Studio

  2. Na Gerenciador de soluções, abra o arquivo Views/Home/Index.cshtml.In Solution Explorer, open the file Views/Home/Index.cshtml. Substitua o código nesse arquivo com o seguinte: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>
    }
    

    Para o serviceUrl variável, use o URI do aplicativo de serviço Web.For the serviceUrl variable, use the URI of the WebService app.

  3. Executar o aplicativo de WebClient localmente ou publicá-lo em outro site.Run the WebClient app locally or publish it to another website.

Quando você clica no botão "Experimente", uma solicitação AJAX é enviada para o aplicativo de serviço Web usando o método HTTP listado na caixa suspensa (GET, POST ou 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). Isso permite que você examinar as solicitações entre origens diferentes.This lets you examine different cross-origin requests. Atualmente, o aplicativo de serviço Web não dá suporte a CORS, portanto, se você clicar no botão, você obterá um erro.Currently, the WebService app does not support CORS, so if you click the button you'll get an error.

'Try' erro no navegador

Note

Se você observar o tráfego HTTP em uma ferramenta como Fiddler, você verá que o navegador envie a solicitação GET e a solicitação for bem-sucedida, mas a chamada do AJAX retorna um erro.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. É importante entender a política de mesma origem não impede que o navegador do enviando a solicitação.It's important to understand that same-origin policy does not prevent the browser from sending the request. Em vez disso, ele impede que o aplicativo vendo os resposta.Instead, it prevents the application from seeing the response.

Depurador da web Fiddler mostrando solicitações da web

Habilitar o CORSEnable CORS

Agora vamos habilitar CORS no aplicativo do serviço Web.Now let's enable CORS in the WebService app. Primeiro, adicione o pacote NuGet de CORS.First, add the CORS NuGet package. No Visual Studio, do ferramentas menu, selecione Gerenciador de pacotes NuGet, em seguida, selecione Package Manager Console.In Visual Studio, from the Tools menu, select NuGet Package Manager, then select Package Manager Console. Na janela do Console do Gerenciador de pacotes, digite o seguinte comando:In the Package Manager Console window, type the following command:

Install-Package Microsoft.AspNet.WebApi.Cors

Este comando instala o pacote mais recente e atualiza todas as dependências, incluindo as bibliotecas de API da Web principal.This command installs the latest package and updates all dependencies, including the core Web API libraries. Use o -Version sinalizador para direcionar uma versão específica.Use the -Version flag to target a specific version. O pacote CORS requer Web API 2.0 ou posterior.The CORS package requires Web API 2.0 or later.

Abra o arquivo App_Start/WebApiConfig.cs.Open the file App_Start/WebApiConfig.cs. Adicione o seguinte código para o Webapiconfig método: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 }
            );
        }
    }
}

Em seguida, adicione a [EnableCors] atributo para o TestController classe: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...
    }
}

Para o origens parâmetro, use o URI de onde você implantou o aplicativo de WebClient.For the origins parameter, use the URI where you deployed the WebClient application. Isso permite que solicitações entre origens do WebClient, enquanto ainda desautorizando todas as outras solicitações entre domínios.This allows cross-origin requests from WebClient, while still disallowing all other cross-domain requests. Posteriormente, descreverei os parâmetros para [EnableCors] em mais detalhes.Later, I'll describe the parameters for [EnableCors] in more detail.

Não inclua uma barra invertida no final de origens URL.Do not include a forward slash at the end of the origins URL.

Reimplante o aplicativo de serviço Web atualizado.Redeploy the updated WebService application. Você não precisa atualizar o WebClient.You don't need to update WebClient. Agora a solicitação AJAX do WebClient deve ser bem-sucedida.Now the AJAX request from WebClient should succeed. Os métodos GET, PUT e POST todos são permitidos.The GET, PUT, and POST methods are all allowed.

Mensagem de teste com êxito de mostrando de navegador da Web

Como funciona o CORSHow CORS Works

Esta seção descreve o que acontece em uma solicitação CORS no nível das mensagens HTTP.This section describes what happens in a CORS request, at the level of the HTTP messages. É importante entender como funciona o CORS, para que você possa configurar o [EnableCors] atributo corretamente e solucionar problemas se as coisas não funcionam conforme o esperado.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.

A especificação CORS apresenta vários novos cabeçalhos HTTP que permitem que solicitações entre origens.The CORS specification introduces several new HTTP headers that enable cross-origin requests. Se um navegador oferece suporte a CORS, ele define esses cabeçalhos automaticamente para solicitações entre origens; Você não precisa fazer nada especial em seu código 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.

Aqui está um exemplo de uma solicitação entre origens.Here is an example of a cross-origin request. O cabeçalho de "Origem" fornece o domínio do site que está fazendo a solicitação.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

Se o servidor permite que a solicitação, ele define o cabeçalho Access-Control-Allow-Origin.If the server allows the request, it sets the Access-Control-Allow-Origin header. O valor desse cabeçalho corresponde o cabeçalho de origem, ou é o valor de curinga "*", o que significa que qualquer origem é permitida.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

Se a resposta não incluir o cabeçalho Access-Control-Allow-Origin, a solicitação AJAX falha.If the response does not include the Access-Control-Allow-Origin header, the AJAX request fails. Especificamente, o navegador não permite a solicitação.Specifically, the browser disallows the request. Mesmo se o servidor retorna uma resposta bem-sucedida, o navegador não disponibiliza a resposta para o aplicativo cliente.Even if the server returns a successful response, the browser does not make the response available to the client application.

Solicitações de simulaçãoPreflight Requests

Para algumas solicitações CORS, o navegador envia uma solicitação adicional, chamada de uma "solicitação de simulação," antes de enviar a solicitação real para o recurso.For some CORS requests, the browser sends an additional request, called a "preflight request", before it sends the actual request for the resource.

O navegador pode ignorar a solicitação de simulação se as seguintes condições forem verdadeiras:The browser can skip the preflight request if the following conditions are true:

  • O método de solicitação é GET, HEAD ou POST, eThe request method is GET, HEAD, or POST, and

  • O aplicativo não definir quaisquer cabeçalhos de solicitação que não seja Accept, Accept-Language, Content-Language, Content-Type ou última--ID do evento, eThe application does not set any request headers other than Accept, Accept-Language, Content-Language, Content-Type, or Last-Event-ID, and

  • O cabeçalho Content-Type (se definido) é um dos seguintes: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
    • texto/simplestext/plain

A regra sobre cabeçalhos de solicitação se aplica aos cabeçalhos que o aplicativo define chamando setRequestHeader sobre o XMLHttpRequest objeto.The rule about request headers applies to headers that the application sets by calling setRequestHeader on the XMLHttpRequest object. (A especificação CORS chama esses cabeçalhos de solicitação"autor".) A regra não se aplica aos cabeçalhos de navegador pode definir, como o agente do usuário, o Host ou o comprimento do conteúdo.(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.

Aqui está um exemplo de uma solicitação de simulação: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

A solicitação de simulação usa o método HTTP OPTIONS.The pre-flight request uses the HTTP OPTIONS method. Ele inclui dois cabeçalhos especiais:It includes two special headers:

  • Access-Control-Request-Method: O método HTTP que será usado para a solicitação real.Access-Control-Request-Method: The HTTP method that will be used for the actual request.
  • Access-Control-Request-Headers: Uma lista de cabeçalhos de solicitação que o aplicativo configurado na solicitação real.Access-Control-Request-Headers: A list of request headers that the application set on the actual request. (Novamente, isso não inclui cabeçalhos que define o navegador.)(Again, this does not include headers that the browser sets.)

Aqui está um exemplo de resposta, supondo que o servidor permite que a solicitação: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

A resposta inclui um cabeçalho Access-Control-Allow-Methods que lista os métodos permitidos e, opcionalmente, um cabeçalho Access-Control-Allow-Headers, que lista os cabeçalhos permitidos.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. Se a solicitação de simulação for bem-sucedida, o navegador envia a solicitação real, conforme descrito anteriormente.If the preflight request succeeds, the browser sends the actual request, as described earlier.

Ferramentas usadas comumente para testar os pontos de extremidade com solicitações de simulação OPTIONS (por exemplo, Fiddler e Postman) não enviam os cabeçalhos necessários de opções por padrão.Tools commonly used to test endpoints with preflight OPTIONS requests (for example, Fiddler and Postman) don't send the required OPTIONS headers by default. Confirme se o Access-Control-Request-Method e Access-Control-Request-Headers cabeçalhos são enviados com a solicitação e cabeçalhos de opções cheguem ao aplicativo por meio do 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.

Para configurar o IIS para permitir que um aplicativo ASP.NET receber e lidar com a opção as solicitações, adicione a seguinte configuração para o aplicativo Web. config arquivo no <system.webServer><handlers> seção: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>

A remoção de OPTIONSVerbHandler impede que o IIS tratar as solicitações de opções.The removal of OPTIONSVerbHandler prevents IIS from handling OPTIONS requests. A substituição de ExtensionlessUrlHandler-Integrated-4.0 permite opções solicitações cheguem ao aplicativo, porque o registro do módulo padrão permite somente solicitações GET, HEAD, POST e depuração com URLs sem extensão.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.

Regras de escopo para [EnableCors]Scope Rules for [EnableCors]

Você pode habilitar o CORS por ação, por controlador ou globalmente para todos os controladores de API da Web em seu aplicativo.You can enable CORS per action, per controller, or globally for all Web API controllers in your application.

Por açãoPer Action

Para habilitar o CORS para uma única ação, defina as [EnableCors] atributo no método de ação.To enable CORS for a single action, set the [EnableCors] attribute on the action method. O exemplo a seguir habilita o CORS para o GetItem somente no método.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) { ... }
}

Por controladorPer Controller

Se você definir [EnableCors] na classe do controlador, ele se aplica a todas as ações no controlador.If you set [EnableCors] on the controller class, it applies to all the actions on the controller. Para desabilitar CORS para uma ação, adicione a [DisableCors] atributo à ação.To disable CORS for an action, add the [DisableCors] attribute to the action. O exemplo a seguir habilita o CORS para cada método, exceto PutItem.The 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) { ... }
}

GlobalmenteGlobally

Para habilitar o CORS para todos os controladores de API da Web em seu aplicativo, passe uma EnableCorsAttribute da instância para o EnableCors método: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);
        // ...
    }
}

Se você definir o atributo em mais de um escopo, a ordem de precedência é:If you set the attribute at more than one scope, the order of precedence is:

  1. AçãoAction
  2. ControladorController
  3. GlobalGlobal

Defina as origens permitidasSet the allowed origins

O origens parâmetro do [EnableCors] atributo especifica quais origens têm permissão para acessar o recurso.The origins parameter of the [EnableCors] attribute specifies which origins are allowed to access the resource. O valor é uma lista separada por vírgulas das origens permitidas.The value is a comma-separated list of the allowed origins.

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

Você também pode usar o valor de curinga "*" para permitir solicitações de qualquer origem.You can also use the wildcard value "*" to allow requests from any origins.

Considere cuidadosamente antes de permitir que solicitações de qualquer origem.Consider carefully before allowing requests from any origin. Isso significa que, literalmente, qualquer site possa fazer chamadas AJAX para sua API da web.It means that literally any website can make AJAX calls to your web API.

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

Defina os métodos HTTP permitidosSet the allowed HTTP methods

O métodos parâmetro do [EnableCors] atributo especifica quais métodos HTTP têm permissão para acessar o recurso.The methods parameter of the [EnableCors] attribute specifies which HTTP methods are allowed to access the resource. Para permitir que todos os métodos, use o valor de curinga "*".To allow all methods, use the wildcard value "*". O exemplo a seguir permite que somente as solicitações GET e 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() { ... }    
}

Definir os cabeçalhos de solicitação permitidoSet the allowed request headers

Este artigo descreveu anteriormente como uma solicitação de simulação pode incluir um cabeçalho Access-Control-Request-Headers, listando os cabeçalhos HTTP definidos pelo aplicativo (os chamados "author cabeçalhos de solicitação").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"). O cabeçalhos parâmetro do [EnableCors] atributo especifica quais cabeçalhos de solicitação do autor são permitidos.The headers parameter of the [EnableCors] attribute specifies which author request headers are allowed. Para permitir que todos os cabeçalhos, defina cabeçalhos para "*".To allow any headers, set headers to "*". Para cabeçalhos específicos de lista de permissões, defina cabeçalhos a uma lista separada por vírgula de cabeçalhos permitidos: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: "*")]

No entanto, os navegadores não são totalmente consistentes em como eles definir Access-Control-Request-Headers.However, browsers are not entirely consistent in how they set Access-Control-Request-Headers. Por exemplo, o Chrome atualmente inclui "origem".For example, Chrome currently includes "origin". FireFox não inclui cabeçalhos padrão, como "Aceitar", mesmo quando o aplicativo define-los no script.FireFox does not include standard headers such as "Accept", even when the application sets them in script.

Se você definir cabeçalhos para qualquer coisa diferente de "*", você deve incluir pelo menos "accept", "content-type" e "origem", além de quaisquer cabeçalhos personalizados que você deseja dar suporte.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.

Definir os cabeçalhos de resposta permitidosSet the allowed response headers

Por padrão, o navegador não expõe todos os cabeçalhos de resposta para o aplicativo.By default, the browser does not expose all of the response headers to the application. Os cabeçalhos de resposta que estão disponíveis por padrão são:The response headers that are available by default are:

  • Cache-ControlCache-Control
  • Idioma do conteúdoContent-Language
  • Tipo de conteúdoContent-Type
  • ExpiraExpires
  • Última modificaçãoLast-Modified
  • PragmaPragma

A especificação CORS chama esses cabeçalhos de resposta simples.The CORS spec calls these simple response headers. Para disponibilizar outros cabeçalhos para o aplicativo, defina as exposedHeaders parâmetro do [EnableCors].To make other headers available to the application, set the exposedHeaders parameter of [EnableCors].

No exemplo a seguir, o controlador Get método define um cabeçalho personalizado chamado 'X-Custom-Header'.In the following example, the controller's Get method sets a custom header named ‘X-Custom-Header'. Por padrão, o navegador não irá expor esse cabeçalho em uma solicitação entre origens.By default, the browser will not expose this header in a cross-origin request. Para disponibilizar o cabeçalho, incluir 'X-Custom-Header' em exposedHeaders.To 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;
    }
}

Passar credenciais nas solicitações entre origensPass credentials in cross-origin requests

Credenciais exigem tratamento especial em uma solicitação CORS.Credentials require special handling in a CORS request. Por padrão, o navegador não envia todas as credenciais com uma solicitação entre origens.By default, the browser does not send any credentials with a cross-origin request. As credenciais incluem cookies, bem como os esquemas de autenticação HTTP.Credentials include cookies as well as HTTP authentication schemes. Para enviar as credenciais com uma solicitação entre origens, o cliente deve definir XMLHttpRequest.withCredentials como true.To send credentials with a cross-origin request, the client must set XMLHttpRequest.withCredentials to true.

Usando o XMLHttpRequest diretamente:Using XMLHttpRequest directly:

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

No jQuery:In jQuery:

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

Além disso, o servidor deve permitir que as credenciais.In addition, the server must allow the credentials. Para permitir credenciais entre origens na API da Web, defina as SupportsCredentials propriedade como true na [EnableCors] atributo: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)]

Se essa propriedade for true, a resposta HTTP incluirá um cabeçalho Access-Control-Allow-Credentials.If this property is true, the HTTP response will include an Access-Control-Allow-Credentials header. Esse cabeçalho informa ao navegador que o servidor permite que as credenciais para uma solicitação entre origens.This header tells the browser that the server allows credentials for a cross-origin request.

Se o navegador envia as credenciais, mas a resposta não inclui um cabeçalho Access-Control-Allow-Credentials válido, o navegador não exporá a resposta para o aplicativo e a solicitação AJAX falhar.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.

Tenha cuidado sobre a configuração SupportsCredentials como true, porque significa que um site em outro domínio pode enviar credenciais do usuário conectado à sua API da Web em nome do usuário, sem que o usuário estar ciente.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. A especificação CORS também declara que a configuração origens à " * " não é válido se SupportsCredentials é verdadeiro.The CORS spec also states that setting origins to "*" is invalid if SupportsCredentials is true.

Provedores de política CORS personalizadosCustom CORS policy providers

O [EnableCors] atributo implementa o ICorsPolicyProvider interface.The [EnableCors] attribute implements the ICorsPolicyProvider interface. Você pode fornecer sua própria implementação, criando uma classe que deriva de atributo e implementa ICorsPolicyProvider.You 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);
    }
}

Agora você pode aplicar o atributo de qualquer lugar que você colocaria [EnableCors].Now you can apply the attribute any place that you would put [EnableCors].

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

Por exemplo, um provedor de política CORS personalizado pode ler as configurações de um arquivo de configuração.For example, a custom CORS policy provider could read the settings from a configuration file.

Como uma alternativa ao uso de atributos, você pode registrar um ICorsPolicyProviderFactory objeto cria ICorsPolicyProvider objetos.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;
    }
}

Para definir a ICorsPolicyProviderFactory, chame o SetCorsPolicyProviderFactory método de extensão na inicialização, da seguinte maneira: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();

        // ...
    }
}

Suporte ao navegadorBrowser support

O pacote de CORS da API Web é uma tecnologia do lado do servidor.The Web API CORS package is a server-side technology. O navegador do usuário também precisa oferecer suporte a CORS.The user's browser also needs to support CORS. Felizmente, as versões atuais de todos os principais navegadores incluem suporte para CORS.Fortunately, the current versions of all major browsers include support for CORS.