Spring boot enable Global CORS support issue: only GET is working, POST, PUT and Delete are not working
Solution 1
I had a a similar issue, only HEAD GET and POST were working for me.
I found out that addCorsMappings
has a default value for allowedMethods
.
This code works for me:
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;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
public class MyConfiguration {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedMethods("*")
.allowedOrigins("http://localhost:4200");
}
};
}
}
Solution 2
I had the same problem - GET worked. POST didn't. I looked for an answer in the CORS domain but eventually, found that it was due to CSRF protection. To solve it, I disabled CSRF protection in the security configuration:
@Configuration @EnableWebSecurity
public class SpringWebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
**.csrf().disable()** //TODO: for production, must be reconfigured in order to disable only in specific cases. This line was added because without it, HTTP POST requests did not work.
.authorizeRequests()
.antMatchers("/api/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
Make sure you understand what you're doing: https://docs.spring.io/spring-security/site/docs/current/reference/html/web-app-security.html#csrf
Solution 3
Try to change allowedOrigins
method to .allowedOrigins("*")
. Postman is an extension and it runs in another "host".
But make sure that you understand the impacts: https://spring.io/understanding/CORS
Solution 4
I faced the same issue and after doing research what i found is, the browser looks for an HTTP header named Access-Control-Allow-Origin in the response.
The browser sends an OPTION request to find out what methods like PUTs, DELETE are allowed. If the requested method is allowed from server side, then the browser will make the actual request, again passing or blocking the response depending on the Access-Control-Allow-Origin header in the response. Simply add a spring bean, that will solve your problem.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration
public class RestConfig {
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("GET");
config.addAllowedMethod("POST");
config.addAllowedMethod("PUT");
config.addAllowedMethod("DELETE");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
Half Ass Dev
Updated on December 17, 2021Comments
-
Half Ass Dev over 2 years
Update: Now looking back more than a year later, I am giving an update hope that will help someone else.
Spring IO recommend using CSRF protection for any request that could be processed by a browser by normal users. If you are only creating a service that is used by non-browser clients, you will likely want to disable CSRF protection. Since my app is an API and will be processed by a browser, so disable CSRF is not an approach.
CSRF is enabled with Spring Boot by default, you would need to add the following code to add a CSRF repository and a filter to add the CSRF token to your http requests. (The solution comes from here Invalid CSRF Token in POST request )
@Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/assets/**", "/templates/**", "/custom-fonts/**", "/api/profile/**", "/h2/**").permitAll() .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") .permitAll() .and() .logout() .logoutSuccessUrl("/login?logout") .permitAll() .and() .csrf().csrfTokenRepository(csrfTokenRepository()) .and() .addFilterAfter(csrfHeaderFilter(), SessionManagementFilter.class); // Register csrf filter. }
The filter & CsrfToken Repository part:
private Filter csrfHeaderFilter() { return new OncePerRequestFilter() { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName()); if (csrf != null) { Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN"); String token = csrf.getToken(); if (cookie == null || token != null && !token.equals(cookie.getValue())) { // Token is being added to the XSRF-TOKEN cookie. cookie = new Cookie("XSRF-TOKEN", token); cookie.setPath("/"); response.addCookie(cookie); } } filterChain.doFilter(request, response); } }; } private CsrfTokenRepository csrfTokenRepository() { HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository(); repository.setHeaderName("X-XSRF-TOKEN"); return repository; }
Original Question I asked back in Feb 2016
I working on enabeing the Global CORS support for a Spring-boot RESTful API with Spring 4.
I am following the official Spring Boot Doc(https://spring.io/guides/gs/rest-service-cors/) and have added this to my Application:
public class SomeApiApplication { public static void main(String[] args) { SpringApplication.run(SomeApiApplication.class, args); } //Enable Global CORS support for the application @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurerAdapter() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("http://localhost:8080") .allowedMethods("GET", "POST", "PUT", "DELETE", "HEAD") .allowedHeaders("header1", "header2") //What is this for? .allowCredentials(true); } }; } }
I don't get why only GET is working, for the rest of http calls, I am getting an error message saying "Invalid CORS request". Do I miss anything in the set up? If my set up is not right, GET should not work as well. I am very confussed.