Spring Boot : CORS Issue
Solution 1
Although Spring security provides a way to configure CORS in http configurer, there's a much cleaner approach to add CORS filter to the application-
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class MyCORSFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me");
chain.doFilter(req, res);
}
@Override
public void init(FilterConfig filterConfig) {
}
@Override
public void destroy() {
}
}
Ordering the filter with highest precedence makes sure that MyCORSFilter implementation of javax.servlet.Filter
is the first one in the chain. Hope this helps
Solution 2
Checkout this guide from Spring:
https://spring.io/guides/gs/rest-service-cors/
There are few ways to add CORS support in Spring Boot.
Using global configuration:
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/greeting-javaconfig").allowedOrigins("http://localhost:9000");
}
};
}
And using @CrossOrigin
annotation:
@CrossOrigin(origins = "http://localhost:9000")
@GetMapping("/greeting")
public Greeting greeting(@RequestParam(required=false, defaultValue="World") String name) {
System.out.println("==== in greeting ====");
return new Greeting(counter.incrementAndGet(), String.format(template, name));
}
Solution 3
There is no need of adding any additional Filters
or WebMvcConfigurer
. The main problem is 'Access-Control-Allow-Origin'
does not present in the header because corsConfigurationSource
does not add the necessary configuration to get the relevant CORS response headers. Hence, the below missing configurations have to be added when we configure CorsConfigurationSource
configuration.addAllowedOrigin("*");
configuration.addAllowedHeader("*");
configuration.addAllowedMethod("*");
We have to configure cors CorsConfigurationSource
as below
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.cors().configurationSource(corsConfigurationSource())
.and()
.....
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("GET","POST"));
configuration.setAllowCredentials(true);
//the below three lines will add the relevant CORS response headers
configuration.addAllowedOrigin("*");
configuration.addAllowedHeader("*");
configuration.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
If anyone facing CORS
issue with Spring Boot 2.4.0 plus versions when having the following combination then refer to answer
CorsConfigurationSource#setAllowedOrigins
value as*
and
CorsConfigurationSource#setAllowCredentials
value astrue
Solution 4
Ok, so I realized that it was deprecated. If you look on baeldung it has how to do it the new way since they updated webmvcconfigurer:
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedMethods("*").allowedOrigins(frontDomain);
}
}
Mohit Kanwar
An enthusiastic developer who loves to design and program applications for Internet.
Updated on July 09, 2022Comments
-
Mohit Kanwar almost 2 years
I am using Spring Boot version 2.0.2Release. Below is my security configuration
@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity( prePostEnabled = true, securedEnabled = true, jsr250Enabled = true) @ComponentScan("com.mk") public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private AuthenticationProvider myAuthenticationProvider; @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable(); http.cors().configurationSource(corsConfigurationSource()) .and() .csrf().disable() .anonymous().and() .authorizeRequests() .antMatchers(HttpMethod.GET,"/index.html").permitAll() .antMatchers(HttpMethod.POST,"/login").permitAll() .antMatchers(HttpMethod.GET,"*").authenticated() .and().httpBasic(); } @Bean CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); configuration.setAllowedOrigins(Arrays.asList("*")); configuration.setAllowedMethods(Arrays.asList("GET","POST")); configuration.setAllowCredentials(true); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return source; }
I am unable to invoke any API (including login which is permitAll) because of CORS issue.
On Browser I am getting (It works with Postman, since CORS check is not made there)
Failed to load http://localhost:8080/myurl: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access. The response had HTTP status code 403.
-
Paulo van Goethe almost 6 yearsYou don't have to use @EnableWebMvc I don't think . If you have that, spring boot won't auto configure the mvc.
-
Paulo van Goethe almost 6 yearsAlso, what's the point of cors if you are going to allow all origins which is what your code says.
-
Mohit Kanwar almost 6 yearsYou are correct regarding allowing all origins, this is a sample code that I am using for testing.
-
Mohit Kanwar almost 6 yearsThis one works for me. with the only issue being that this is being invoked multiple times in same request.
-
Paulo van Goethe almost 6 yearsOk, I figured something like that was going on.
-
priteshbaviskar almost 6 yearsIt can be the case that it is called for every single request made by browser apart from your api call. For eg. css, icons, images etc.
-
Mohit Kanwar almost 6 yearsnot the css/icons etc because they are hosted on different server, but let me check
-
The Dnino over 5 years@MohitKanwar Try to use OncePerRequestFilter , public class CustomFIlter extends OncePerRequestFilter
-
Tomas Lukac over 4 yearsThis didn't work for me, but this did: stackoverflow.com/a/36821971/8092044
-
GalAbra about 3 yearsWhy do you
addAllowedOrigin("*")
after you'vesetAllowedOrigins(Arrays.asList("*"))
? -
Prasanth Rajendran about 3 yearsyes, you can remove the following
addAllowedOrigin("*")
as we have already addedsetAllowedOrigins(Arrays.asList("*"))
, I added just to illustrate multiple option is possible to add the origins -
JSON derulo almost 3 yearsBut if you remove these duplicate lines then it's the same code as in OP's question, no? I don't get it, I have my config like you said, but still preflight has "No Allow Origin Header"...