CORS for Dummies: O que todo DEV deve saber a respeito.

Israel Fonseca
mercos-engineering
Published in
4 min readOct 17, 2016

Primeira coisa: todos os navegadores devem respeitar o conceito de Same-origin-policy.

Same-origin-policy?

Sim, ela garante que as respostas de todas as requisições feitas, só possam ser lidas se feitas do mesmo domínio. Um exemplo rápido: abra o www.google.com e faça um GET no console para outro domínio.

Tente fazer um fetch no Twitter a partir de qualquer outro site para ver a treta acontecendo.

Por causa do Same-Origin-Policy o navegador te disse de uma maneira simpática que "Você não tem acesso para ler a resposta do servidor".

Apenas a resposta?

Sim. No exemplo anterior a requisição de fato foi feita no servidor, mas o navegador se negou a exibir a resposta. Se alguém tivesse implementado uma rotina qualquer (como envio de e-mail) ela teria sido executada. O seu navegador apenas escondeu a resposta do servidor.

Certo, mas eu criei uma API Pública e quero que qualquer domínio acesse ela. Como faço? Não tem como?

Tem, é ai que entra em cena o CORS (Cross Origin Resource Sharing), que como o nome tenta indicar, permite que o server comunique ao navegador que suas respostas possam ser lidas através de um outro domínio.

É isso que eu preciso… Como eu configuro esse CORS?

É simples, a especificação define uma série de headers que devem ir na resposta para comunicar ao browser que o server está disposto a receber aquela requisição cross-domain.

Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Origin: *
Access-Control-Max-Age: 3600

A lista de headers com mais detalhes você pode ver aqui, mas a mais importante é a Access-Control-Allow-Origin que é preenchida com a lista de domínios cujo o server está apto a receber/processar requests, opcionalmente, um * pode ser utilizado para indicar que todos os domínios podem enviar requisições.

Ok, então se eu não configurar o CORS nas respostas eu não poderei ver a resposta, mas a requisição sempre será processada no servidor?

Depende. A especificação do CORS define dois tipos de requisições. As simple-requests e as pre-flight-requests.

Simple-requests? WTF?

Bom, antigamente, no período pre-CORS, já era possível fazer requests para outros domínios, porém apenas para alguns tipos de requests, as chamadas simple-requests. Elas basicamente são do tipo GET e POST que não possuem headers personalizados, ou seja, provavelmente enviadas através de um formulário HTML. No caso do POST, há algumas restrições para que seja considerada uma simple-request, são permitidos como content-type apenas os valores "text/plain" e "application/x-www-form-urlencoded", mais detalhes aqui.

Hmm… E as outras requests, as pre-flight-request?

Para as requests que não se enquadram como simple-requests, o navegador faz uma request extra do tipo OPTIONS antes de executar de fato a request. Desta forma, o browser dá a possibilidade do server informar se aceita ou não a request.

Tá, mas com essa request extra, o tempo de latência para uma requisição será dobrada, sabendo que o server sempre processa as requests de qualquer forma, não bastava só os headers na resposta?

Não, antigamente os navegadores respeitavam a Same-Origin-Policy, com o CORS, algumas das restrições foram relaxadas, com isso, foi aberta uma margem para ataques em sistemas mais antigos, que não contavam que um dia alguma request cross-domain fosse feita.

Hmmm…

Por exemplo, imagine que você acessa o internet banking, e está sempre logado, caso você acesse algum site com um código javascript fazendo uma request para o site do seu banco, passando informações de uma transferência qualquer, ela será feita sem problemas. Apenas a resposta não estará disponível, mas neste caso, a resposta é o de menos, já que você nem saberá que isso aconteceu, a não ser que acompanhe tudo que acontece no console do seu navegador.

Ok, então as pre-flight-requests fazem primeiro um OPTIONS verificando se a request é permitida, e caso seja, só aí a request original será feita?

Sim, caso o OPTIONS seja rejeitado, nada será processado pelo servidor, caso aprovado, a request original será enviada automaticamente pelo browser.

Resumindo, em um primeiro momento, acreditava-se que seria melhor se as requests só podiam ser feitas dentro de um mesmo domínio, porém, em algum momento, percebeu-se que seria interessante permitir cross-domain requests, mas simplesmente quebrar a Same-Origin-Policy seria perigoso demais, com isso surgiu o CORS, que específica algumas coisas para permitir que as requests cross-domains pudessem ser realizadas, só que um pouco mais seguras.

Sim. Mas o CORS não traz segurança para o servidor, ele tenta proteger o lado do cliente de possíveis ataques, por isso, é importante técnicas de segurança no lado do servidor contra ataques como do tipo do CSRF.

CSRF?

Sim… Mas isso é outro assunto.

Esta obra de arte é um trabalho colaborativo entre Israel Fonseca e Hudolf Hess.

--

--