Compartilhamento de recursos entre origens (CORS, na sigla em inglês)

Compartilhar recursos entre origens com segurança

Mariko Kosaka

A política de mesma origem do navegador impede a leitura de um recurso de uma origem diferente. Esse mecanismo impede que sites maliciosos leiam dados de outros sites, mas também impede usos legítimos.

Os apps da Web modernos geralmente querem receber recursos de uma origem diferente, por exemplo, recuperar dados JSON de um domínio diferente ou carregar imagens de outro site em um <canvas> elemento. Esses podem ser recursos públicos que devem estar disponíveis para qualquer pessoa ler, mas a política de mesma origem bloqueia o uso deles. Os desenvolvedores usam soluções alternativas, como JSONP.

O Compartilhamento de recursos entre origens (CORS) corrige esse problema de maneira padronizada. A ativação do CORS permite que o servidor informe ao navegador que ele pode usar uma origem adicional.

Como uma solicitação de recurso funciona na Web?

solicitação e resposta
Solicitação do cliente e resposta do servidor ilustradas.

Um navegador e um servidor podem trocar dados pela rede usando o Hypertext Transfer Protocol (HTTP). O HTTP define as regras de comunicação entre o solicitante e o respondente, incluindo quais informações são necessárias para receber um recurso.

O cabeçalho HTTP negocia a troca de mensagens entre o cliente e o servidor e é usado para determinar o acesso. A solicitação do navegador e a mensagem de resposta do servidor são divididas em um cabeçalho e um corpo.

Informações sobre a mensagem, como o tipo ou a codificação dela. Um cabeçalho pode incluir uma variedade de informações expressas como pares de chave-valor. O cabeçalho da solicitação e o cabeçalho de resposta contêm informações diferentes.

Exemplo de cabeçalho da solicitação

Accept: text/html
Cookie: Version=1

Esse cabeçalho é equivalente a dizer "Quero receber HTML em resposta. Aqui está um cookie que tenho."

Exemplo de cabeçalho de resposta

Content-Encoding: gzip
Cache-Control: no-store

Esse cabeçalho é equivalente a dizer "Os dados nesta resposta são codificados com gzip. Não armazene isso em cache."

Corpo

A mensagem em si. Pode ser texto simples, um binário de imagem, JSON, HTML ou muitos outros formatos.

Como o CORS funciona?

A política de mesma origem informa ao navegador para bloquear solicitações de origem cruzada. Quando você precisa de um recurso público de uma origem diferente, o servidor que fornece o recurso informa ao navegador que a origem que envia a solicitação pode acessar o recurso. O navegador se lembra disso e permite o compartilhamento de recursos entre origens para esse recurso.

Etapa 1: solicitação do cliente (navegador)

Quando o navegador faz uma solicitação entre origens, o navegador adiciona um cabeçalho Origin com a origem atual (esquema, host e porta).

Etapa 2: resposta do servidor

Quando um servidor vê esse cabeçalho e quer permitir o acesso, ele adiciona um cabeçalho Access-Control-Allow-Origin à resposta especificando a origem da solicitação (ou * para permitir qualquer origem).

Etapa 3: o navegador recebe a resposta

Quando o navegador vê essa resposta com um cabeçalho Access-Control-Allow-Origin adequado, ele compartilha os dados de resposta com o site do cliente.

Compartilhar credenciais com o CORS

Por motivos de privacidade, o CORS é normalmente usado para solicitações anônimas, em que o solicitante não é identificado. Se você quiser enviar cookies ao usar o CORS, que podem identificar o remetente, adicione outros cabeçalhos à solicitação e à resposta.

Solicitação

Adicione credentials: 'include' às opções de busca, como no exemplo a seguir. Isso inclui o cookie com a solicitação da seguinte maneira:

fetch('https://example.com', {
  mode: 'cors',
  credentials: 'include'
})

Resposta

Access-Control-Allow-Origin precisa ser definido como uma origem específica (sem curinga usando *) e Access-Control-Allow-Credentials precisa ser definido como true.

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true

Solicitações de simulação para chamadas HTTP complexas

Quando um app da Web faz uma solicitação HTTP complexa, o navegador adiciona uma solicitação de pré-voo ao início da cadeia de solicitações.

A especificação CORS define uma solicitação complexa da seguinte maneira:

  • Uma solicitação que usa métodos diferentes de GET, POST ou HEAD.
  • Uma solicitação que inclui cabeçalhos diferentes de Accept, Accept-Language ou Content-Language.
  • Uma solicitação que tem um cabeçalho Content-Type diferente de application/x-www-form-urlencoded, multipart/form-data ou text/plain.

Os navegadores criam automaticamente todas as solicitações de pré-voo necessárias e as enviam antes da mensagem de solicitação real. A solicitação de pré-voo é uma solicitação OPTIONS, como no exemplo a seguir:

OPTIONS /data HTTP/1.1
Origin: https://example.com
Access-Control-Request-Method: DELETE

No lado do servidor, o app que recebe a solicitação responde à solicitação de pré-voo com informações sobre os métodos que o aplicativo aceita dessa origem:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, DELETE, HEAD, OPTIONS

A resposta do servidor também pode incluir um cabeçalho Access-Control-Max-Age para especificar a duração em segundos para armazenar em cache os resultados de simulação. Isso permite que o cliente envie várias solicitações complexas sem precisar repetir a solicitação de pré-voo.