Entenda o que é o erro CORS
1. O erro mais comum no frontend moderno
Se você trabalha com React, Angular ou qualquer frontend separado do backend, já viu isso:
Access to fetch at 'http://localhost:8080/api'
from origin 'http://localhost:3000'
has been blocked by CORS policyE normalmente a primeira reação é:
"o backend tá errado"
"o frontend não conecta"
"vou liberar tudo com *"
Calma. Vamos entender antes de sair liberando geral.
2. O que é CORS (na prática)
CORS (Cross-Origin Resource Sharing) é uma política de segurança do navegador.
Ela impede que um frontend acesse um backend que está em outra origem.
Origem = combinação de:
protocolo (http / https)
domínio
porta
Exemplo:
http://localhost:3000
http://localhost:8080👉 São origens diferentes, mesmo sendo localhost.
3. Por que o erro acontece
Fluxo:
Frontend faz requisição para outro domínio
Navegador bloqueia por segurança
Backend precisa autorizar explicitamente
👉 Se o backend não autoriza, o navegador barra
Importante:
o erro NÃO é do backend diretamente
é o navegador protegendo o usuário
4. Tipos de requisição CORS
Requisição simples
GET / POST simplesPreflight (OPTIONS)
OPTIONS /api👉 O navegador pergunta antes:
"posso acessar esse recurso?"
Se o backend não responder corretamente: 👉 erro CORS
5. Solução correta no Spring Boot
Configuração global (recomendado)
@Configuration
public class CorsConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:3000")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true);
}
};
}
}6. Configuração com Spring Security (obrigatório em produção)
Se você usa Spring Security, isso muda.
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.csrf(csrf -> csrf.disable())
.cors(cors -> {})
.authorizeHttpRequests(auth -> auth
.anyRequest().authenticated()
)
.build();
}👉 Se não ativar .cors(), nada funciona.
7. Liberar tudo (não faça isso em produção)
.allowedOrigins("*")Problemas:
risco de segurança
expõe sua API
permite qualquer domínio
👉 Use só em ambiente local
8. Configuração correta para produção
.allowedOrigins(
"https://seusite.com",
"https://admin.seusite.com"
)👉 Sempre listar explicitamente
9. CORS com cookies e JWT
Se você usa:
cookies
sessões
autenticação
Precisa disso:
.allowCredentials(true)E no frontend:
fetch(url, {
credentials: "include"
})10. Problema comum com OPTIONS
Se sua API bloqueia OPTIONS:
👉 preflight falha
Solução:
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")11. Teste prático
Backend rodando:
http://localhost:8080Frontend:
http://localhost:3000Se estiver configurado corretamente: requisição funciona
12. Erros mais comuns
esquecer
.cors()no Securitynão liberar OPTIONS
usar "*" com credenciais
esquecer porta diferente
configurar no controller apenas
13. Quando usar @CrossOrigin
@CrossOrigin(origins = "http://localhost:3000")
@RestController
public class UserController {
}Bom para testes, Evite em produção (use config global)
14. Conclusão
CORS não é erro.
É segurança.
Quando você entende:
por que existe
como funciona
onde configurar
nunca mais perde tempo com isso
