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 bloqueia a leitura de um recurso de uma origem diferente. Esse mecanismo impede que sites maliciosos leiam os 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, recuperando dados JSON de um domínio diferente ou carregando imagens de outro site em um elemento <canvas>. Eles podem ser recursos públicos que precisam estar disponíveis para qualquer pessoa ler, mas a política de mesma origem bloqueia o uso deles. Os desenvolvedores já usaram soluções alternativas, como o 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 pode usar uma origem adicional.

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

solicitação e resposta
Ilustração de solicitação do cliente e resposta do servidor.

Um navegador e um servidor podem trocar dados pela rede usando o protocolo de transferência de hipertexto (HTTP). O HTTP define as regras de comunicação entre o solicitante e o respondente, incluindo quais informações são necessárias para acessar 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 de solicitação e o cabeçalho de resposta contêm informações diferentes.

Exemplo de cabeçalho de solicitação

Accept: text/html
Cookie: Version=1

Esse cabeçalho equivale 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 equivale a dizer "Os dados nessa resposta são codificados com gzip. Não armazene em cache."

Corpo

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

Como funciona o CORS?

A política de mesma origem instrui o navegador a 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 de diferentes origens, ele adiciona um cabeçalho Origin com a origem atual (esquema, host e porta).

Etapa 2: resposta do servidor

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

Etapa 3: o navegador recebe uma resposta

Quando o navegador encontra 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 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 pode identificar o remetente, adicione cabeçalhos adicionais à 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 caractere curinga usando *) e Access-Control-Allow-Credentials 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 simulada 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 simulação é uma solicitação OPTIONS, como no exemplo abaixo:

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 aceitos pelo aplicativo 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 da simulação. Isso permite que o cliente envie várias solicitações complexas sem precisar repetir a solicitação de simulação.