DEV Community

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

Posted on

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... 😉

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.