Configurando CORS em projetos Spring Boot

Quem nunca tentou integrar um front-end com um back-end e recebeu um erro parecido com esse aqui:
Access to XMLHttpRequest at ‘http://localhost:8080/api/v1/resource’ from origin ‘http://localhost:3000’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

Ou ainda recebendo como resposta HTTP 403, de um recurso que você tem certeza que tem permissão para acessar.

Bom se isso está acontecendo com você, saiba que você está sendo bloqueado pela politica de CORS da api backend, e se o backend está escrito usando o framework Spring Boot, veio ao lugar certo vamos ensinar você a ajustar isso e parar de receber esse erro.

O que é CORS

CORS na verdade quer dizer Cross-Origin Resource Sharing é um mecanismo que permite restringir recursos de um domínio, que serão recuperados por outro domínio.

Basicamente funciona da seguinte forma os recursos de um domínio só podem ser recuperados se a chamada vier do mesmo domínio em caso de a chamada vir de outro domínio essa chamada é bloqueada evitando que os recursos sejam recuperados.

Basicamente o funcionamento do CORS está restritos aos browsers, se você está tendo um erro com a chamada, e tentar fazer a mesma chamada por um software de requisições REST como Postman ou o Insominia, vai perceber que esse erro não acontece.

Isso porque o browser (Navegador de internet) é quem é responsável por fazer a verificação de Cross-Origin.

Configurando o CORS no Spring Boot

Por padrão o Spring Boot, vem definido para aceitar requisições apenas do próprio domínio, para configurar o recebimento de outros domínios, basta fazer a seguinte configuração:

package com.artefatox.example.controller;

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class GreetingController {
    
    @CrossOrigin(origins = "*")
    @GetMapping("/greeting")
    public String greeting(@RequestParam("name") String name) {
        return "Olá " + name;
    }
}
Java

Nessa configuração básica usamos a annotation @CrossOrigin e na propriedade origins que recebe um Array de strings podemos definir os domínios permitidos nesse endpoint.

Note também que essa configuração vai afetar apenas esse endpoint, e da forma que configuramos estamos permitindo aceitar requisições de qualquer outro domínio, pois estamos usando o coringa *.

Dependendo de como sua aplicação vai ser exposta e o nível de acesso que você pretende delimitar para ela é interessante colocar a url do próprio domínio ao invés do coringa *.

Para aplicar mais de um domínio nessa configuração pode-se usar o exemplo abaixo:

package com.artefatox.example.controller;

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class GreetingController {
    
    @CrossOrigin(origins = { "example1.com", "example2.com" })
    @GetMapping("/greeting")
    public String greeting(@RequestParam("name") String name) {
        return "Olá " + name;
    }
}
Java

Mas então se eu tiver 10 endpoints vou precisar marcar todos com a configuração de CORS? Bom a resposta é não, é possível em aplicações Spring Boot configurar de forma global na sua aplicação, fazendo com que todos os endpoints sejam afetados.

Configurando o CORS de maneira global

Para que a configuração de Cross-Origin funcione de forma global vamos precisar criar uma classe de configuração com um @Bean que vai retornar a nossa configuração toda vez que acontece o start da aplicação.

package com.artefatox.example.controller;

import org.springframework.context.annotation.Bean;
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 WebConfiguration {

    @Bean
    public WebMvcConfigurer webMvcConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry
                    .addMapping("/**")
                    .allowedOrigins("*")
                    .allowedHeaders("*")
                    .allowedMethods("*");
            }
        };
    }
}
Java

Explicando cada definição

  • addMapping: Essa propriedade mapeia os endpoints que serão aplicados a configuração, ao adicionar “/**” estamos definindo que apartir da raiz todos os endpoints serão afetados.
  • allowedOrigins: Nessa propriedade podemos passar os domínios que poderão acessar a aplicação, no nosso caso estamos usando o coringa * que significa que qualquer domínio poderá consumir os recursos.
  • allowedHeaders: Aqui você pode definir quais os headers que você aceitará na requisição, nesse caso estamos definindo que vamos aceitar todos os headers.
  • allowedMethods: Aqui é possível definir os métodos HTTP que serão permitidos, nessa caso também estamos aceitando todos.

Lembrando essas configurações devem ser pensadas para o tipo de aplicação que você está desenvolvendo, se precisar de uma configuração mais restritiva é possível setar as configurações para que sejam aceitos somente alguns domínios, ou alguns métodos ou até permitir apenas alguns headers. Ex.

package com.artefatox.example.controller;

import org.springframework.context.annotation.Bean;
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 WebConfiguration {

    @Bean
    public WebMvcConfigurer webMvcConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry
                    .addMapping("/api/v1/**")
                    .allowedOrigins("example1.com", "examplo2.com")
                    .allowedHeaders("Authorization", "Content-Type", "Accept")
                    .allowedMethods("GET", "POST", "PUT");
            }
        };
    }
}
Java

Agora com o Cross-Origin devidamente configurado pode fazer todos os testes necessários e verá que o erro que estava recebendo no front-end não acontece mais.

Configuração no Front-end

Se o erro persiste mesmo tendo feito as devidas configurações, vale lembrar que é importante verificar na sua aplicação front-end se o jeito como está sendo chamado o recurso está correto, se a chamada está passando todos os headers necessários.

Bibliotecas como o Axios que é bastante utilizada com aplicações escritas em React por exemplo, tendem a apresentar erro de CORS, mesmo a chamada apresentando outros tipos de erros, então vale uma análise mais detalhada do erro.

Aqui está alguns exemplos de headers que podem ser passados na requisição que ajudam com esses erros:

"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "Authorization", 
"Access-Control-Allow-Methods": "GET, POST, OPTIONS, PUT, PATCH, DELETE"
Text

Links Uteis

Mauricio Lima
Mauricio Lima

Bacharel em Ciência da Computação, profissional dedicado ao desenvolvimento de software e entusiasta da tecnologia.

Artigos: 65