July 16, 2020
Json-P

JSON é um formato leve de intercâmbio de dados. Foi formalmente padronizado por Douglas Crockford e, desde então, foi recebido quase universalmente como uma representação simples e poderosa de dados para transmissão entre duas entidades, independentemente da linguagem de computador em que essas entidades são executadas nativamente.

Ajax entre domínios - breve introdução

A política de mesma origem nos navegadores determina que certos tipos de transferência de dados na camada do navegador (via JavaScript) devem ser restritos a ocorrer apenas se o domínio do recurso de destino for idêntico à página que faz a solicitação. Esta política está em vigor em todos os navegadores modernos para ajudar a proteger os usuários contra comportamentos JavaScript maliciosos indesejados ou inseguros.

O Ajax entre domínios refere-se à idéia de fazer solicitações entre domínios em oposição à restrição de mesma origem. No entanto, o Ajax entre domínios não é inerentemente inseguro ou ruim - é de fato essencial para muitos dos mashups mais populares e úteis do mundo. Mas o Ajax de domínio cruzado feito corretamente procura fazer essa comunicação usando técnicas que, por várias razões, não estão sujeitas à política de mesma origem.

JSON-P (JSONP)

Um desses mecanismos que podem solicitar conteúdo entre domínios é a tag <script> . Em dezembro de 2005, Bob Ippolito propôs formalmente o JSONP (posteriormente chamado de JSON-P ou JSON-pad-padding) como uma maneira de aproveitar essa propriedade de tags <script> para poder solicitar dados no formato JSON entre domínios. O JSON-P funciona criando um elemento <script> (na marcação HTML ou inserido no DOM via JavaScript), que solicita um local de serviço de dados remoto. A resposta (o conteúdo “JavaScript” carregado) é o nome de uma função predefinida na página da web solicitante, com o parâmetro sendo passado para os dados JSON solicitados. Quando o script é executado, a função é chamada e transmitida pelos dados JSON, permitindo que a página solicitante receba e processe os dados.

Exemplo:

função handle_data (data) {
   // `data` agora é a representação do objeto dos dados JSON
}


---
http: //some.tld/web/service? callback = handle_data:
---
handle_data ({"data_1": "olá mundo", "data_2": ["the", "sun", "is", "shining"]});

Como você pode ver, o serviço da Web remoto sabia para qual nome da função chamar, com base na indicação do nome da função na URL que fez a solicitação. Desde que essa função seja realmente definida na página solicitante, ela será chamada e transmitida pelos dados que estava solicitando.

O problema

Até agora, o JSON-P tem sido essencialmente uma definição flexível por convenção, quando, na realidade, o navegador aceita qualquer JavaScript abitrar na resposta. Isso significa que os autores que confiam no JSON-P para o Ajax entre domínios estão, de fato, se abrindo a potencialmente tanto caos quanto se tentou evitar ao implementar a política de mesma origem em primeiro lugar. Por exemplo, um serviço da Web mal-intencionado pode retornar uma chamada de função para a parte JSON-P, mas incluir outro conjunto de lógica JavaScript que corrompe a página e envia dados de usuário privado etc.

O JSON-P é, por esse motivo, visto por muitos como uma abordagem insegura e hacky para o Ajax entre domínios, e por boas razões. Os autores devem ser diligentes em fazer apenas chamadas para serviços da Web remotos nos quais eles controlam ou confiam implicitamente, para não sujeitar seus usuários a danos.

Alternativas

Existem muitas alternativas ao JSON-P, mas cada uma delas tem suas próprias desvantagens ou desafios. Essas técnicas não serão abordadas em detalhes aqui, exceto uma: CORS (também conhecida como “Compartilhamento de recursos entre origens”) - a adição mais recente ao JavaScript do navegador para fazer chamadas Ajax entre domínios. Simplificando, o CORS é uma extensão do objeto XMLHttpRequest (também conhecido como “XHR”), que permite ao navegador fazer chamadas entre domínios (apesar da restrição de mesma origem). Porém, isso é feito “pré-confirmando” uma solicitação ao servidor de destino para pedir permissão.

Em outras palavras, o servidor remoto pode ativar ou desativar a comunicação que considerar adequada. Por exemplo, um servidor pode expor algum conteúdo às solicitações do Ajax apenas de uma lista predefinida de domínios de sites aprovados e rejeitar todas as outras solicitações de outras páginas. Ou, um servidor pode abrir seu conteúdo para ser recuperado por qualquer outro domínio, se achar conveniente.

À primeira vista, pode parecer que o CORS é uma solução ideal para o Ajax entre domínios e torna obsoletos “hacks” como o JSON-P. Nicholas Zakas escreveu recentemente sobre o CORS para o Ajax entre domínios e deu a ele um endosso brilhante como o futuro do Ajax entre domínios nos navegadores.

Ainda não se sabe se o CORS como o “padrão” será amplamente implementado e utilizado para o amplo uso de Ajax entre domínios na Web. Existem algumas desvantagens, é claro, pois o diabo está sempre nos detalhes.

Em primeiro lugar, o CORS requer um servidor que implemente um serviço da Web para implementar alguma lógica não trivial para interceptar cabeçalhos de solicitação nas solicitações de autorização especiais “preflight” e responder com cabeçalhos de resposta formatados corretamente, dependendo da resposta de diretiva pretendida do servidor. Se um serviço da Web JSON precisar oferecer suporte a solicitações de domínio cruzado com o JSON-P, é uma alteração bastante simples envolver a parte JSON em uma simples chamada de função.

Porém, pedir aos serviços da web na Internet que implementem a lógica de nível inferior na camada de servidor da web para enviar e receber cabeçalhos personalizados especiais é possivelmente um pouco mais complicado, dependendo do software e das permissões do servidor da web. Pode levar vários anos para que essa técnica seja compreendida e chegue ao ponto em que a maioria dos provedores de serviços da Web seja compatível com CORS. A partir de agora, é muito novo e poucos serviços da Web o fizeram, em oposição a dezenas de milhares de terminais de serviços da Web habilitados para JSON-P existentes.

Além disso, o CORS foi implementado (embora com algumas pequenas diferenças sintáticas) apenas a partir do IE8, e ainda não no Opera (tanto quanto se sabe). Portanto, há uma boa parte dos visitantes da Web cujo navegador não suporta o CORS, o que significa que um fallback para o Ajax entre domínios alternativo ainda será necessário a médio prazo (1 a 3 anos, talvez).

A solução proposta

Por enquanto, o JSON-P é uma solução viável para o Ajax entre domínios. Embora o CORS possa representar uma maneira mais direta e menos hacky de tal comunicação, provavelmente deve ser implantado em conjunto com as técnicas JSON-P, de modo a dar conta de navegadores e serviços da Web que não suportam o CORS. No entanto, as preocupações de segurança em torno do JSON-P são válidas e devem ser abordadas.

Portanto, é necessária uma definição de subconjunto mais rigorosa para JSON-P. A seguir, é apresentado o “padrão” proposto apenas para o que deve ser considerado JSON-P válido, seguro e permitido.

nome_da_função ({JSON});

obj.functionName ({JSON});

obj ["nome da função"] ({JSON});

A intenção é que apenas uma única expressão (referência de função ou referência de função de propriedade de objeto) possa ser usada para a referência de função (“padding”) da resposta JSON-P e deve ser imediatamente seguida por um único par () envolvente, dentro do qual deve ser um objeto JSON estritamente válido e analisável. A chamada de função pode opcionalmente ser seguida por uma; ponto e vírgula. Nenhum outro conteúdo, além de espaço em branco ou comentários válidos do JavaScript, pode aparecer na resposta JSON-P, e o espaço em branco e os comentários devem ser ignorados pelo analisador de JavaScript do navegador (como seria normalmente o caso).

A parte mais crítica desta proposta é que os fornecedores de navegadores devem começar a aplicar essa regra para as tags de script que estão recebendo conteúdo JSON-P e gerar erros (ou pelo menos interromper o processamento) em qualquer conteúdo JSON-P não conforme.

Para que o navegador possa saber quando deve aplicar essa filtragem de conteúdo ao que de outra forma poderia ser visto como conteúdo JavaScript comum, o tipo MIME “application / json-p” e / ou “text / json-p” deve ser declarado no elemento <script> solicitante. Além disso, o navegador pode impor que a resposta deve ser do tipo MIME correspondente ou falhar com erros também.

Desvantagens

É sabido que os navegadores existentes que não suportam o CORS também provavelmente não serão atualizados para suportar essa aplicação estrita do JSON-P, o que significa que os usuários desses navegadores não serão protegidos pelo navegador. No entanto, todos os navegadores atuais podem adicionar suporte a essa filtragem de conteúdo, o que forneceria JSON-P mais seguro para os usuários atuais do navegador que estão consumindo dados de serviços da web que ainda não suportam CORS (ou para os quais o autor não deseja usar o CORS para qualquer razão).

Também é reconhecido que essa definição mais rígida pode causar a transmissão de algumas transmissões “JSON-P”, que se baseiam na interpretação mais vaga de conteúdo JavaScript apenas arbitrário. Mas isso poderia ser facilmente evitado fazendo com que o autor (e o servidor) evitem se referir a esse conteúdo com os tipos MIME JSON-P estritamente definidos, conforme descrito acima, o que impediria o navegador de ativar seletivamente essa filtragem.

Nota

Uma possível técnica de mitigação que poderia ajudar os usuários de navegadores mais antigos a aproveitar a segurança do JSON-P seria o autor detectar navegadores sem esse suporte (discutindo como esse teste de recurso pode funcionar) e direcionar condicionalmente essas solicitações apenas para aqueles navegadores não seguros por meio de um proxy do servidor local (ou mesmo por um proxy flash do lado do cliente, como o flXHR ), que poderia atuar como um gateway para o conteúdo e executar a lógica de filtragem descrita acima.

Um efeito colateral importante da codificação de um padrão para JSON-P é que uma implementação do analisador pode (e será) ser escrita para verificar a definição estrita. Esse analisador pode ser facilmente usado no proxy do servidor local ou no proxy flash do lado do cliente para filtrar conteúdo não seguro / inválido que deveria ter sido JSON-P estrito.

Caso de uso alternativo: teste de unidade

Outro caso de uso interessante para ter um padrão para JSON-P no qual um analisador pode ser gravado é a noção de poder testar APIs de unidade que produzem saída JSON-P. Por exemplo, esse teste é comum para APIs JSON, usando algo como JSONLint, mas para APIs JSON-P no momento, não há uma boa maneira de bombear a saída por algum analisador para validá-la.

Avançando

Essa é uma primeira passagem dessa definição para JSON-P seguro. Por meio deste, abro a discussão para a comunidade em geral para avaliar os prós e os contras e colaborar juntos para encontrar uma definição viável que possa ser defendida pelos fornecedores do W3C, WHATWG e navegador.

A melhor maneira de se envolver é escrever posts em resposta a esta proposta e criar links para essas discussões. Além disso, a marcação / código deste site está hospedada no github , e você pode bifurcar e modificar a página para continuar a discussão e, em seguida, enviar uma solicitação de recebimento para atualizar o site. Por fim, você pode fazer comentários curtos no formulário de comentários abaixo, mas por favor, mantenha seus comentários breves e objetivos, pois eles serão moderados conforme necessário para manter a discussão nos trilhos.