Soluções para Cross-Origin: JSONP e CORS em Detalhe

Cross-origin é uma restrição de segurança implementada pelos navegadores para evitar que scripts acessem recursos de origens diferentes. Entre as principais abordagens para resolver isso estão JSONP e CORS. Outras soluções, como proxies, são abordadas em discussões separadas.

JSONP

JSONP (JSON with Padding) é uma técnica que aproveita a flexibilidade das tags <script> para contornar a mesma política de origem. A ideia é encapsular os dados JSON em uma chamada de função callback.

O prcoesso funciona da seguinte forma:

  1. O cliente insere dinamicamente uma tag <script> no documento, definindo o atributo src como o endpoint da API. Isso limita o método a GET.
  2. O srevidor recebe a requisição, extrai o parâmetro de callback (ex.: callbackFunc) dos query parameters.
  3. O servidor prepara a resposta no formato callbackFunc({"dados": "exemplo"}) e a retorna com o cabeçalho Content-Type: application/javascript; charset=utf-8.
  4. O navegaodr executa o script retornado, invocando a função callback com os dados.

Exemplo de código no cliente:

function processarDados(resultado) {
  console.log('Dados recebidos:', resultado);
}

const scriptTag = document.createElement('script');
scriptTag.src = 'http://api.servidor.com/dados?callback=processarDados';
document.body.appendChild(scriptTag);

Desvantagens do JSONP:

  • Suporta apenas requisições GET.
  • Dificuldade no debugging, pois erros não retornam códigos de status HTTP adequados.
  • Riscos de segurança, como injeção de código se o serviço JSONP for comprometido.

Vantagens:

  • Compatível com navegadores antigos que não suportam CORS.
  • Permite acesso a recursos em servidores sem configuração de CORS.

CORS

CORS (Cross-Origin Resource Sharing) é um mecanismo que utiliza cabeçalhos HTTP para permitir ou restringir acesso cross-origin. Ele se divide em requisições simples e não-simples.

Requisições Simples

Uma requisição é considerada simples se:

  • O método HTTP é HEAD, GET ou POST.
  • Os cabeçalhos personalizados estão restritos a Accept, Accept-Language, Content-Language, Last-Event-ID ou Content-Type com valores específicos (application/x-www-form-urlencoded, multipart/form-data, text/plain).

Para requisições simples, o navegador inclui automaticamente o cabeçalho Origin na requisição. O servidor responde com cabeçalhos como:

  • Access-Control-Allow-Origin: Especifica a origem permitida (ex.: http://cliente.com) ou * para qualquer origem.
  • Access-Control-Allow-Credentials: Se true, permite o envio de cookies.
  • Access-Control-Expose-Headers: Lista de cabeçalhos adicionais acessíveis pelo cliente.

Exemplo de cabeçalhos na resposta do servidor:

Access-Control-Allow-Origin: http://cliente.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: X-Info

Para enviar cookies, o cliente deve configurar a propriedade withCredentials em requisições AJAX:

const xhr = new XMLHttpRequest();
xhr.open('GET', 'http://api.servidor.com/dados', true);
xhr.withCredentials = true;
xhr.onreadystatechange = function() {
  if (xhr.readyState === 4 && xhr.status === 200) {
    console.log(xhr.responseText);
  }
};
xhr.send();

Requisições Não-Simples

Requisições que não atendem aos critérios simples, como métodos PUT ou DELETE, ou cabeçalhos personalizados, geram uma requisição de pré-verificação (preflight). O navegador envia uma requisição OPTIONS para o servidor, incluindo:

  • Origin: A origem do cliente.
  • Access-Control-Request-Method: O método HTTP a ser usado.
  • Access-Control-Request-Headers: Cabeçalhos personalizados que serão enviados.

Exemplo de requisição preflight:

OPTIONS /recurso HTTP/1.1
Origin: http://cliente.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Token

O servidor responde com os cabeçalhos CORS apropriados:

Access-Control-Allow-Origin: http://cliente.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: X-Token, Content-Type
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 86400

Após a pré-verificação bem-sucedida, o navegador prossegue com a requisição original. Os cabeçalhos Access-Control-Allow-Methods e Access-Control-Allow-Headers são relevantes apenas na resposta ao OPTIONS, enquanto Access-Control-Allow-Origin deve estar presente tanto na preflight quanto na requisição real para autorização.

Tags: JSONP CORS Cross-Origin HTTP Headers Preflight Request

Publicado em 6-15 02:21 por Thomas