O CORS (Cross-origin Resource Sharing) é um mecanismo utilizado pelos navegadores para compartilhar recursos entre diferentes origens. O CORS é uma especificação do W3C e faz uso de headers do HTTP para informar aos navegadores se determinado recurso pode ser ou não acessado.
Para compreender melhor, imagine que você está desenvolvendo uma aplicação web que consiste em uma SPA e uma API. Tudo ocorre sem problemas no seu ambiente local, mas ao fazer o deploy em produção você se depara com isso:
Isso acontece devido a um mecanismo de segurança presentes nos navegadores chamado de same-origin policy. Ele é usado para limitar como um documento ou script de uma origem pode interagir com recursos de outra origem.
Curso WordPress - Criação de Plugins
Conhecer o cursoEntenda como origem a combinação entre o protocolo (http ou https), o host (painel.treinaweb.com.br) e a porta (80 ou 443, podendo ser omitida) de um determinado endereço (http://painel.treinaweb.com.br/
). Se a origem de duas URLs forem idênticas, a interação entre esses recursos pode acontecer sem problema.
Por exemplo, considere a seguinte URL: http://painel.treinaweb.com.br/perfil/
. Alguns exemplos de URLs com same-origin considerando a origem são http://painel.treinaweb.com.br/
e http://painel.treinaweb.com.br/cursos/
. Nesses casos a única alteração está no path, com o início da URL igual.
Agora, as seguintes URLs seriam bloqueadas: https://painel.treinaweb.com.br/perfil/
, http://painel.treinaweb.com.br:81/perfil/index.html
, http://www.treinaweb.com.br/
. No primeiro caso, o protocolo é diferente (https), no segundo caso temos outra porta e, por fim, o subdomínio do host é diferente.
Em todos esses casos você está sujeito a uma requisição controlada por CORS:
Possíveis erros de CORS
Como a utilização e compartilhamento de recursos de origens diferentes é algo bastante comum na internet, nem tudo que o navegador precisa carregar está sujeito ao same-origin policy. Sua página está sujeita a algum tipo de problema de CORS em requisições como:
- XMLHttpRequest ou Fetch API do Javascript;
- Web fonts, utilizando a funcionalidade de @font-face do CSS;
- WebGL textures;
- CSS Shapes
- Imagens em canvas desenhados com drawImage()
Os casos mais comuns são com as requisições javascript que utilizam XMLHttpRequest ou Fetch APIs. Para esses casos vamos entender como o CORS funciona e como podemos solucionar corretamente esse problema.
Curso Nest.js - Templates com Handlebars
Conhecer o cursoCiclo de uma requisição com CORS
Ao enviar uma requisição para uma origem diferente, o navegador utiliza de um header específico enviado pelo servidor chamado Access-Control-Allow-Origin
. A partir desse e mais alguns headers o navegador determina se aquele recurso será carregado ou não.
Em alguns tipos de requisições, é necessário enviar uma requisição preliminar chamada de preflighted request. O preflighted request utiliza o método OPTIONS do HTTP informando o método e domínio que será invocado para assim garantir que a requisição seguinte pode ser realizada.
Temos abaixo um diagrama que mostra como funciona uma requisição que precisa enviar uma chamada de preflight:
Como resolver problemas de CORS
Quando encontramos um erro de CORS, é importante verificar qual requisição esta causando esse problema diretamente no console do seu navegador. Geralmente o problema é causado pela ausência de headers no lado do servidor.
Para corrigir esse problema, garanta que o servidor está enviando os seguintes headers na sua resposta:
Access-Control-Allow-Origin: https://perfil.treinaweb.com.br
Access-Control-Allow-Methods: POST, GET
Access-Control-Allow-Headers: *
Access-Control-Max-Age: 86400
Nesse exemplo, estamos permitindo que a origem https://perfil.treinaweb.com.br
acesse os recursos daquele servidor, sendo possível o uso dos métodos HTTP GET e POST, juntamente com qualquer header adicional. Para os casos de preflight request, temos também o header Access-Control-Max-Age
que funciona como um cache, em segundos, para essa request.
Tenha uma atenção especial ao header Access-Control-Allow-Origin
. Você pode utilizar *
como sua origin ou até em partes dela (https://*.treinaweb.com.br
por exemplo, para incluir todos os subdomínios da TreinaWeb), mas tente sempre limitar para origens conhecidas da sua aplicação, evitando assim que origens desconhecidas acessem seus servidores.
Como enviar esses headers vai variar dependendo da linguagem ou servidor da sua aplicação. Como por exemplo, com express você pode definir os headers necessários usando um middleware de CORS:
var express = require('express')
var cors = require('cors')
var app = express()
app.use(cors())
app.get('/products/:id', function (req, res, next) {
res.json({msg: 'This is CORS-enabled for all origins!'})
})
app.listen(80, function () {
console.log('CORS-enabled web server listening on port 80')
})
Caso você não tenha acesso ao código da sua aplicação, você pode configurar seu servidor web, como o Apache, para retornar esses headers:
Header set Access-Control-Allow-Origin "*"
Em outros casos, pode ser configurar o serviço que você está consumindo, como o S3 da Amazon. Esses serviços podem ser configuráveis com regras específicas para atender esses casos, porém isso varia de serviço a serviço.
Conclusão
Nesse artigo conhecemos o que significa de fato o CORS e como podemos resolver esses tipos de problemas. Existem algumas outras configurações que podem ser feitas para implementar o CORS nas suas aplicações, como o suporte a requests com credentials que não abordamos aqui.
Para saber mais, temos uma excelente referência da Mozilla que explica em detalhes como funciona o CORS.