Spring Boot
Contornando erro de CORS no Java com Spring Boot
Por que o navegador bloqueia chamadas entre origens diferentes, o que CORS realmente é (e não é), riscos de abrir tudo em produção — e como configurar CORS no Spring Boot com WebMvcConfigurer.
Você já estava montando um projeto pessoal, um MVP ou um teste para vaga e, ao ligar o front na API local, apareceu CORS?
O erro no console costuma ser parecido com:
Access to fetch at
http://localhost:8080/api/...from originhttp://127.0.0.1:5500has been blocked by CORS policy: NoAccess-Control-Allow-Originheader is present on the requested resource.
Se estiver com prazo curto, pode ir direto à seção Spring Boot e depois volta aqui com calma para o “porquê”.
O que é CORS?
CORS (Cross-Origin Resource Sharing) é um mecanismo em que o servidor declara quais outras origens podem chamar a API a partir do navegador. O bloqueio que você vê é a política de mesma origem do browser + a ausência (ou restrição) desses cabeçalhos na resposta.
Ou seja: não é “bug do Java” nem “bug do React” primeiro — é o navegador exigindo que a API diga explicitamente quem pode consumir aquele recurso em requisições cross-origin.
Exemplo clássico
- Front:
http://localhost:3000(ex.: React) - API:
http://localhost:8080(Spring Boot)
Origens diferentes (scheme, host ou porta mudou) ⇒ para fetch/XHR o browser faz o fluxo CORS (incluindo preflight em muitos casos). Se o backend não responder com as permissões corretas, a requisição falha no cliente mesmo que a API “funcione” se você chamar com Postman ou curl.
CORS “não é um erro”?
Em sentido estrito: é uma camada de segurança. O console chama de erro, mas o que acontece é o browser recusando expor a resposta ao seu JS porque o servidor não autorizou aquela origem.
Isso não diminui a dor no desenvolvimento — só ajuda a lembrar que a correção é configurar o servidor (e a política) com consciência, não “desligar segurança” no escuro.
Same-Origin Policy em uma frase
Por padrão, o browser limita o que uma página pode ler de outra origem. CORS é o jeito controlado de o servidor dizer: “estas origens podem acessar estes recursos, com estes métodos e cabeçalhos”.
Por que isso importa em produção?
Abrir CORS para “qualquer um” (* ou lista gigante sem critério) não substitui autenticação/autorização e pode aumentar superfície de abuso quando combinado com sessões/credenciais mal modeladas.
Pontos que o artigo original trazia e que continuam válidos:
- CSRF e uso indevido de cookies/sessão em outro site — mitigação de verdade costuma envolver tokens anti-CSRF, SameSite, CORS restrito e desenho de API; CORS sozinho não “fecha” o problema.
- Exposição de dados: se qualquer origem puder consumir endpoints sensíveis só porque o CORS está folgado, você facilita cenários ruins.
- APIs sem camada de auth adequada: CORS não é substituto de JWT, OAuth, políticas de autorização, etc.
Em produção, o ideal é listar apenas origens confiáveis (ex.: https://www.seudominio.com).
Atenção
Não use Access-Control-Allow-Origin: * em produção quando há credenciais (cookies, Authorization em cenários sensíveis) — e, de modo geral, evite * para API que entrega dado sensível. Prefira origens explícitas.
Para origens dinâmicas (vários subdomínios, ambientes), dá para usar allowedOriginPatterns (Spring) com critério claro, em vez de “liberar o mundo”.
Como configurar CORS no Spring Boot
Crie uma classe de configuração que implementa WebMvcConfigurer e sobrescreva addCorsMappings.
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins(
"http://localhost:3000",
"http://127.0.0.1:5500"
)
.allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true);
}
}
O que cada parte faz:
addMapping: path da API (/**para tudo, ou prefixos como/api/**).allowedOrigins: origens do front que podem chamar a API (troque pelos seus hosts reais).allowedMethods: verbos HTTP permitidos no CORS.allowedHeaders: cabeçalhos que o browser pode enviar (em dev,*é comum; em produção você pode restringir).allowCredentials(true): necessário quando você usa cookies ou cenários que exigem credenciais na requisição cross-origin — lembre-se da regra: não combine*emAllow-Origincom credenciais; use origem explícita (como no exemplo).
Variante com padrão de origem (Spring Boot 2.4+)
Quando fizer sentido validar por padrão (ex.: subdomínios de um domínio seu), use allowedOriginPatterns em vez de listar dezenas de URLs fixas — ainda assim com critério, não *.
registry.addMapping("/api/**")
.allowedOriginPatterns("https://*.seudominio.com")
.allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true);
Considerações finais
API costuma ser última linha antes do dado sensível: CORS é só uma peça do desenho — authN/authZ, validação, rate limit e modelo de sessão/token importam tanto quanto.
O objetivo aqui foi ir além de “copiar config e seguir”: entender por que o browser bloqueia, o que configurar no Spring e por que em produção a lista de origens deve ser enxuta e intencional.