
Spring security cors csrf preflight aplicacao: evite erros em
Quando a sua spring security cors csrf preflight aplicacao começa a receber chamadas de um front-end separado, os primeiros erros aparecem rápido: bloqueio de CORS, falha no preflight, 403 em requisições autenticadas e dúvidas sobre CSRF. Por outro lado, no Spring Boot, isso costuma acontecer justamente quando a API sai do ambiente local e passa a ser consumida por SPA, mobile ou uma arquitetura com domínios diferentes. Se voce quiser comparar essa abordagem com outro cenario comum no ecossistema Spring, vale revisar Como Criar uma API REST com Spring Boot em 15 Minutos [Guia Rápido].
O problema não é “liberar tudo” nem “travar tudo”. Por outro lado, o caminho correto é entender o papel de CORS, CSRF e do preflight, e configurar o Spring Security para aceitar apenas o que faz sentido para o seu cenário. Ao mesmo tempo, em API REST com JWT e sessão stateless, por exemplo, a estratégia muda bastante em relação a uma aplicação tradicional com login via cookie. Para complementar esse ponto com um exemplo proximo do dia a dia, consulte JWT Spring Boot Java: Guia Completo com Exemplo Prático.
Se você já tem uma base de API no Spring Boot e quer revisar a parte estrutural antes de mexer em segurança, vale consultar o conteúdo sobre Como Criar uma API REST com Spring Boot em 15 Minutos [Guia Rápido]. Por outro lado, para um contexto maior de segurança, também faz sentido cruzar este tema com Como proteger APIs REST com Spring Security: autorização, filtro JWT e fluxo stateless. Esse detalhe conversa bem com o que eu mostrei em Controller vs RestController no Spring Boot: Qual usar em APIs REST?.
Spring security cors csrf preflight aplicacao: secao pratica com codigo completo
Na pratica, um exemplo enxuto ajuda a sair da teoria e evitar erro comum de producao quando o projeto cresce. Se quiser aprofundar o assunto por outro angulo, leia tambem Como proteger APIs REST com Spring Security: autorização, filtro JWT e fluxo stateless.
@Component
public class JwtAuthFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
String header = request.getHeader("Authorization");
if (header != null && header.startsWith("Bearer ")) {
// validar token e montar autenticacao
}
chain.doFilter(request, response);
}
}Spring Security CORS CSRF Preflight Aplicacao: o que cada peça faz
Antes de configurar, vale separar as responsabilidades. Por outro lado, cORS não é uma proteção do servidor contra ataque; é uma política do navegador para permitir ou negar requisições vindas de outra origem. Ao mesmo tempo, se seu front roda em localhost:3000 e a API em localhost:8080, o navegador trata isso como origens diferentes. Na prática, sem CORS liberado, a chamada nem chega a ser útil para o front. Quando esse tipo de duvida aparece em projeto real, eu costumo voltar neste material: JWT no Spring Security com Spring Boot: autenticação moderna passo a passo.
CSRF é outra história. Por outro lado, ele protege principalmente aplicações que usam sessão e cookie para autenticação, porque o navegador envia cookies automaticamente em requisições para o mesmo domínio. Ao mesmo tempo, se um atacante conseguir induzir o navegador do usuário a chamar sua aplicação autenticada, a sessão pode ser reutilizada sem intenção do usuário. Na prática, em APIs stateless com Authorization Bearer e JWT no header, o risco e o tratamento costumam ser diferentes. Por isso, a decisão de desabilitar CSRF não deve ser “porque sim”; deve seguir o modelo de autenticação do sistema.
O preflight, por sua vez, é a requisição OPTIONS que o navegador faz antes da chamada principal quando a operação é considerada “não simples”. Por outro lado, isso acontece bastante com Content-Type: application/json, headers personalizados como Authorization e métodos como PUT, PATCH e DELETE. Ao mesmo tempo, se o preflight falhar, a chamada real nem acontece. Na prática, em produção, isso costuma aparecer como um erro confuso no front-end, mas a causa está na configuração da API.
Configurar CORS Spring Boot sem abrir o acesso da API inteira
Para configurar CORS Spring Boot de forma segura, o melhor é permitir apenas origens específicas, métodos necessários e headers realmente usados pelo front-end. Por outro lado, liberar * para tudo pode até resolver em desenvolvimento, mas em produção vira um atalho perigoso e desnecessário.
Se sua aplicação usa Spring Security, a configuração de CORS precisa conversar com a cadeia de filtros. Por outro lado, não basta criar um WebMvcConfigurer e achar que o problema acabou, porque o Spring Security pode bloquear a requisição antes mesmo de chegar ao controller. Ao mesmo tempo, em APIs com segurança ativa, o ideal é expor um CorsConfigurationSource e habilitar o suporte a CORS no HttpSecurity.
O exemplo abaixo cobre um cenário real: front-end em domínio diferente, autenticação via JWT no header e API REST sem sessão.
Exemplo completo de configuração
package com.javalizando.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import java.util.List;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(AbstractHttpConfigurer::disable)
.cors(Customizer.withDefaults())
.authorizeHttpRequests(auth -> auth
.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.requestMatchers("/public/**").permitAll()
.anyRequest().authenticated()
);
return http.build();
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(List.of(
"http://localhost:3000",
"https://app.minhaempresa.com"
));
configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
configuration.setAllowedHeaders(List.of("Authorization", "Content-Type", "X-Requested-With"));
configuration.setExposedHeaders(List.of("Authorization"));
configuration.setAllowCredentials(true);
configuration.setMaxAge(3600L);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}Esse código resolve o básico de um jeito que funciona em produção sem deixar a porta escancarada. Por outro lado, note que o OPTIONS foi liberado antes da autenticação. Ao mesmo tempo, isso é importante porque o preflight não carrega token no mesmo formato da requisição final. Na prática, se você esquecer isso, o navegador vai falhar antes do POST real acontecer.
Se o seu front consumir a API com fetch ou axios, cabe revisar também a forma como a aplicação está estruturada. Por outro lado, em cenários com controllers de API, o uso correto de Controller vs RestController no Spring Boot: Qual usar em APIs REST? Ao mesmo tempo, evita comportamento inesperado e ajuda a manter o contrato HTTP mais claro.
CSRF Spring Boot: quando desabilitar e quando manter
Em muita aplicação moderna, a resposta honesta é: se a API é stateless, usa JWT no header Authorization e não depende de cookie para autenticação, desabilitar CSRF costuma ser aceitável. Por outro lado, o motivo é simples: o navegador não envia automaticamente esse token no mesmo sentido que envia um cookie de sessão. Ao mesmo tempo, o vetor clássico de CSRF perde força nesse modelo.
Mas isso não significa que CSRF virou irrelevante. Por outro lado, se a sua aplicação usa login baseado em sessão, formulário tradicional, cookie persistido ou alguma integração híbrida, deixar CSRF desligado pode ser uma brecha séria. Ao mesmo tempo, em muitos times, o erro nasce justamente de copiar a mesma configuração de uma API JWT para uma aplicação web com sessão e depois descobrir isso em auditoria ou incidente.
Em projetos mais maduros, eu gosto de tratar essa decisão como parte do desenho arquitetural. Por outro lado, aPI para app mobile e front SPA separado tende a seguir o padrão stateless. Ao mesmo tempo, já aplicações server-side com browser e cookie autenticado exigem uma leitura mais cuidadosa do CSRF Spring Boot. Na prática, a tecnologia é a mesma; o risco operacional é diferente.
Erros comuns em produção com CORS, CSRF e preflight
O primeiro erro recorrente é liberar CORS em um bean, mas esquecer de habilitar http.cors() na cadeia do Spring Security. Por outro lado, o resultado é um comportamento inconsistente: em alguns cenários o front até parece funcionar, em outros o navegador bloqueia com falha de preflight. Ao mesmo tempo, isso confunde bastante porque a configuração existe, mas não está integrada ao ponto certo do fluxo.
O segundo erro é permitir * com allowCredentials(true). Por outro lado, essa combinação é problemática e, em geral, inválida no navegador. Ao mesmo tempo, quando há credenciais envolvidas, as origens precisam ser explícitas. Na prática, em produção, isso evita que qualquer site tente se beneficiar do seu endpoint.
Outro erro clássico é esquecer de liberar OPTIONS nas rotas protegidas. Por outro lado, a pessoa testa o endpoint com curl ou Postman e conclui que está tudo certo, mas o browser faz preflight e toma 401 ou 403. Ao mesmo tempo, resultado: o back-end parece “instável”, quando na verdade a cadeia de autorização está barrando a verificação inicial.
Também é comum configurar CORS só para GET e POST, ignorando PUT, PATCH e DELETE. Por outro lado, em APIs REST reais, essas operações aparecem o tempo todo. Ao mesmo tempo, se você esquece um método, o front pode funcionar parcialmente e falhar justamente nas operações de atualização e remoção.
Por fim, há a armadilha de desabilitar CSRF em qualquer projeto sem analisar o tipo de autenticação. Por outro lado, em apps com cookie e sessão, isso é um convite a problemas. Ao mesmo tempo, em APIs com JWT no header, faz sentido discutir desativação, mas ainda assim vale registrar a decisão no código e na documentação interna.
Quando usar e quando evitar essa configuração
Use essa abordagem quando sua aplicação for uma API consumida por SPA, front-end separado ou app mobile, com autenticação via token no header e sem dependência de sessão do navegador. Por outro lado, esse é o cenário mais comum em sistemas modernos com Spring Security CORS e CSRF pensados para um fluxo stateless. Ao mesmo tempo, o preflight precisa ser tratado porque o navegador vai exigir isso em chamadas com cabeçalhos customizados e JSON.
Evite aplicar a mesma configuração sem pensar em sistemas que ainda dependem de cookie, sessão HTTP ou páginas renderizadas no back-end. Por outro lado, nesses casos, desabilitar CSRF pode eliminar uma camada importante de defesa. Ao mesmo tempo, também evite expor origens demais só para “parar o erro no browser”. Na prática, se a lista de origens cresce sem critério, o risco aumenta rápido e a manutenção vira dor de cabeça.
Se o seu time está consolidando autenticação JWT, vale cruzar essa parte com JWT no Spring Security com Spring Boot: autenticação moderna passo a passo e com JWT Spring Boot Java: Guia Completo com Exemplo Prático. Por outro lado, esses dois temas se encaixam bem com a decisão de manter a API stateless e simplificar o desenho de segurança.
FAQ sobre Spring Security CORS CSRF Preflight Aplicacao
Por que meu front recebe erro de CORS mesmo com a API funcionando no Postman?
Porque Postman não segue as mesmas restrições do navegador. O browser aplica política de origem e preflight, então uma API pode parecer perfeita em teste manual e ainda assim falhar no front-end. Ao mesmo tempo, isso quase sempre indica configuração incompleta de CORS, método bloqueado ou falha no OPTIONS.
Posso desabilitar CSRF em toda API Spring Boot?
Pode, mas só faz sentido quando a API é stateless e não usa cookies ou sessão como base de autenticação. Por outro lado, se houver login com sessão, páginas server-side ou cookies sensíveis, desabilitar CSRF pode criar risco real.
Como liberar preflight OPTIONS no Spring Security?
O caminho mais estável é permitir OPTIONS na configuração de autorização e habilitar CORS dentro do SecurityFilterChain. Assim, o navegador consegue validar a origem e seguir com a requisição real sem ser bloqueado no primeiro passo.
Conclusão: ajuste a segurança sem transformar a API em porta aberta
O ponto central de uma spring security cors csrf preflight aplicacao bem configurada é equilíbrio. Por outro lado, o front-end precisa falar com a API sem atrito, mas a API não pode aceitar qualquer origem, qualquer método ou qualquer contexto de autenticação. Ao mesmo tempo, em projetos reais, o que resolve não é “desligar a segurança”, e sim modelar corretamente CORS, CSRF e preflight de acordo com o tipo de autenticação.
Se a sua aplicação usa JWT e fluxo stateless, a configuração costuma ficar mais simples: origem explícita, métodos necessários, headers certos, OPTIONS liberado e CSRF desabilitado com intenção clara. Por outro lado, se usa sessão ou cookie, a história muda e o CSRF volta para o centro da discussão.
Como próximo passo, revise o seu SecurityFilterChain, teste as chamadas pelo navegador e valide os headers de resposta no DevTools. Por outro lado, depois, compare essa configuração com a estratégia de autenticação do projeto. Ao mesmo tempo, em segurança, a configuração certa não é a mais permissiva; é a que combina com a arquitetura sem deixar brechas desnecessárias. Na prática, os proximos passos sao validar esse fluxo no seu projeto, ajustar o caso de uso real e cobrir a implementacao com testes.
Spring security cors csrf preflight aplicacao: referencias externas
Para validar detalhes de implementacao e aprofundar a configuracao, vale consultar a documentacao oficial do Spring Security, o guia de claims no JWT.io e a documentacao do Spring Boot.