DEV Community

Jean Carlos Corrêa Couto
Jean Carlos Corrêa Couto

Posted on

1

Configurando CORS Global para API Springboot

Quando temos a necessidade de consumir (ou enviar) dados de uma API para apresentar no frontend construímos diversos endpoints nela para nos auxiliar nesta tarefa e com isso sempre barramos no famigerado CORS (Cross-Origin Resource Sharing) e ele sempre apresenta o mesmo erro no console:

CORS erro - imagem ilustrativa

Então a primeira ação que temos é ir na nossa API, procurar a Controller e adicionar acima no endpoint a anotação do Springframework...

@CrossOrigin ou @CrossOrigin(origins = "*")
Enter fullscreen mode Exit fullscreen mode

...nos livrar do problema e seguir o desenvolvimento da tarefa.
Então nossa API vai crescendo e todo o endpoint exposto para o front vai receber essa mesma anotação do @CrossOrigin.

Chega um momento que você se pergunta se ainda é realmente necessário ter essa anotação ali, ou a validação do Sonar está avisando que esse CORS é uma vulnerabilidade no seu código.

Há uma maneira, até simples, de fazer essa configuração de CORS porém num escopo Global, sem precisar adicionar em todos os endpoints. Para isso, basta criar a seguinte classe na sua estrutura:

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
@EnableWebMvc
class CORSConfiguration implements WebMvcConfigurer {

    @Value("${config.cors.allowed-origins}")
    String[] origins;

    @Value("${config.cors.allowed-headers}")
    String[] headers;

    @Value("${config.cors.allowed-methods}")
    String[] methods;

    @Value("${config.cors.max-age}")
    long maxAge;

    @Value("${config.cors.exposed-headers}")
    String[] exposed;

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowCredentials(true).maxAge(maxAge)
                .allowedOriginPatterns(origins).allowedHeaders(headers)
                .allowedMethods(methods).exposedHeaders(exposed);
    }
}
Enter fullscreen mode Exit fullscreen mode

e também alterar o seu arquivo properties.yml adicionado a seguinte estrutura:

# CORS config
config:
  cors:
    allowed-origins: http://localhost:4200, https://www.url-do-front.com.br
    allowed-methods: GET, POST, PATCH, PUT, DELETE, OPTIONS, HEAD
    max-age: 3600
    allowed-headers: "*"
    exposed-headers: "*"
Enter fullscreen mode Exit fullscreen mode

Explicando aqui:
A classe de configuração implementa a interface nativa do Spring MVC chamada WebMvcConfigurer e com isso você precisa sobrescrever o método: void addCorsMappings(CorsRegistry registry).
Esse método, adiciona em tempo de configuração, as configurações de CORS informadas do arquivo .yml que são recuperadas de lá pela anotação @Value, também do Spring.

Nota: No método addCorsMapping, para a classe CorsRegistry, precisa adicionar o método allowCredentials(true), com ele o Swagger não ficará solicitando credenciais de acesso para carregar a página inicial.

Então quando você der o start no projeto, as configurações serão carregadas e adicionadas ao contexto do CORS, com isso não precisa mais da anotação @CrossOrigin em cada endpoint.

Mas claro, lembrando que cada um tem sua necessidade de implementação do CORS, que isso varia de acordo com cada projeto.

Para minha necessidade atual, funcionou perfeitamente. 😊

Até qualquer dia... 😉

Sentry blog image

How I fixed 20 seconds of lag for every user in just 20 minutes.

Our AI agent was running 10-20 seconds slower than it should, impacting both our own developers and our early adopters. See how I used Sentry Profiling to fix it in record time.

Read more

Top comments (2)

Collapse
 
wldomiciano profile image
Wellington Domiciano

Sua dica de externalizar os dados pro CORS, colocando no application.yml foi bem legal.

Se vc estiver usando Spring Boot, é bom ficar atento com o uso da anotação @EnableWebMvc.

Quando vc usa esta anotação em conjunto com @Configuration vc sobrescreve a auto-configuração que o Spring Boot traz pra gente.

Nisso vc pode acabar perdendo algumas configurações que podem te fazer falta.

Se vc quer tirar proveito da auto-configuração do Spring Boot e apenas adicionar a configurações do CORS, basta usar apenas @Configuration.

Isto é o que a documentação diz:

If you want to keep those Spring Boot MVC customizations and make more MVC customizations (interceptors, formatters, view controllers, and other features), you can add your own @Configuration class of type WebMvcConfigurer but without @EnableWebMvc.

E também:

If you do not want to use the auto-configuration and want to take complete control of Spring MVC, add your own @Configuration annotated with @EnableWebMvc. Alternatively, add your own @Configuration-annotated DelegatingWebMvcConfiguration as described in the Javadoc of @EnableWebMvc.

Fonte: docs.spring.io/spring-boot/docs/3....

Collapse
 
jccorreacouto profile image
Jean Carlos Corrêa Couto

Bem interessante esse ponto. Muito obrigado pela dica.

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Engage with a sea of insights in this enlightening article, highly esteemed within the encouraging DEV Community. Programmers of every skill level are invited to participate and enrich our shared knowledge.

A simple "thank you" can uplift someone's spirits. Express your appreciation in the comments section!

On DEV, sharing knowledge smooths our journey and strengthens our community bonds. Found this useful? A brief thank you to the author can mean a lot.

Okay