'Access-Control-Allow-Origin multiple values with Spring Boot and Vue.JS
I have this class for CORS on my API:
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 CorsConfiguration implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedMethods("*").allowedOrigins("*").allowedHeaders("*");
}
}
Request returns me 200, and this is my answer to frontend:
[Date:"Wed, 10 Jul 2019 18:11:54 GMT", Server:"Apache/2.4.18 (Ubuntu)", Vary:"Authorization", Cache-Control:"no-cache, private", X-Robots-Tag:"noindex", Access-Control-Allow-Origin:"*", Access-Control-Allow-Methods:"POST, GET, PUT, PATCH, DELETE, OPTIONS", Access-Control-Allow-Headers:"Authorization, Content-Type, Accept", Access-Control-Allow-Credentials:"true", Keep-Alive:"timeout=5, max=100", Connection:"Keep-Alive", Transfer-Encoding:"chunked", Content-Type:"application/json"]
But in my console at chrome I see:
Access to XMLHttpRequest at 'http://localhost:3000/api/v1/empresas' from origin 'http://localhost:8080' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed.
My controller:
@GetMapping(value = "empresas", produces = "application/json;charset=UTF-8")
public ResponseEntity listaEmpresa(@NotNull @RequestHeader String authorization) throws IOException {
tokenValidatorService.validaToken(authorization);
return companyModel.listaEmpresas(authorization);
}
What can I do? I don't set up Access Control Allow Origin anytime at my code..
Solution 1:[1]
I usually use this configuration and it works.
Be sure that @Configuration
class is loaded in application context
@Configuration
public class CorsConfiguration {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedHeaders("*")
.allowedMethods("*");
}
};
}
}
If you have a security mechanism that trigger pre-flight request, you have also to allow HttpMethod.OPTIONS
calls on all your application as follows
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class KsSecurity extends WebSecurityConfigurerAdapter {
...
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers(HttpMethod.OPTIONS, "/**") // <---------- You need this
.antMatchers(
"/**/*.{js,html,css,ico}",
"/i18n/**",
"/assets/**",
"/v2/api-docs/**",
"/webjars/**",
"/swagger-resources/**",
"/swagger-ui.html");
}
...
}
Solution 2:[2]
If your are using spring-cloud-gateway api then try below
spring: cloud: gateway: globalcors: corsConfigurations: '[/]': allowed-origins: "" allowed-methods: "" allowed-headers: "" allow-credentials: true
routes:
- id: login-users
uri: http://localhost:1000/
filters:
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin
predicates:
- Path=/login/v1/post/login
- Method=POST
- id: loginservice
uri: http://localhost:1001/
predicates:
- Path=/login/v1/**
- Method=POST
Solution 3:[3]
I had this same error in following scenario.
I have Springboot RESTAPI and Angular client.
Angular Client calls the API and all end points are behaving as expected.
CAUSE (IN MY SCENARIO)
However, one endpoint in my API calls another API.
That other API returns response including the headers containing its own Access-Control-Allow-Origin. Then my API adds its own Access-Control-Allow-Origin resulting in two Access-Control-Allow-Origin headers which is not allowed by browsers.
My CORS settings are right because I know all other endpoints are working fine and are returning only one Access-Control-Allow-Origin.
SOLUTION
Thanks to @RobbyofTheFozenPeas So, the solution I did is that in the Controller calling other API, and once other API returns response, I would get the body out of that response and create a new ResponseEntity from it.
This results in only my API returning its own Access-Control-Allow-Origin and all is working fine.
I hope this explanation of the cause and solution will help others since I see lots of people are asking the same question.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Jeelan |
Solution 3 | pixel |