Spring Global CORS configuration not working but Controller level config does

36,744

Solution 1

In order for the global CORS config to work, the client must add these two headers in the OPTIONS request.

Origin: http://host.com
Access-Control-Request-Method: POST

However the @CrossOrigin annotation requires just the "Origin" header.
Your client probably adds the "Origin" header but is missing the "Access-Control-Request-Method".....thats why it works for you with the @CrossOrigin, but doesn't with the global config.

Solution 2

you didn't declared method in it which is by default accept only get method. try registry.allowedMethods("*");

Solution 3

I was facing the same issue and after setting the maxAge attribute everything started working ok!

@Bean
public WebMvcConfigurer CORSConfigurer() {
    return new WebMvcConfigurer() {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**")
                    .allowedOrigins("*")
                    .allowedHeaders("*")
                    .allowedMethods("GET", "POST", "PUT", "DELETE", "HEAD")
                    .maxAge(-1)   // add maxAge
                    .allowCredentials(false);
        }
    };
}

if you check the CrossOrigin annotation it has a default value assigned to that attribute

/**
 * <p>By default this is set to {@code 1800} seconds (30 minutes).
 */
long maxAge() default -1;

Solution 4

I've just been having the exact same issue, with none of the solutions in this thread working. I've managed to solve it with the following:

A new configuration bean:

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsFilterConfiguration {

  @Bean
  public CorsFilter corsFilter() {
      UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
      CorsConfiguration config = new CorsConfiguration();
      config.setAllowCredentials(true);
      config.addAllowedOrigin("*");
      config.setAllowedMethods(Arrays.asList("POST", "OPTIONS", "GET", "DELETE", "PUT"));
      config.setAllowedHeaders(Arrays.asList("X-Requested-With", "Origin", "Content-Type", "Accept", "Authorization"));
      source.registerCorsConfiguration("/**", config);
      return new CorsFilter(source);
  }
}

A modification to my web.xml to add a new filter for all URLs:

<filter>
  <filter-name>corsFilter</filter-name>
  <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
  <filter-name>corsFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

Obviously you can modify the cors config accordingly.

Solution 5

I faced similar issue. I changed the WebMvcConfigurerAdapter to WebMvcConfigurationSupport and it started working.

In addition to this I also moved the RequestMappingHandlerMapping defined in xml configuration file to java configuration.

Share:
36,744
Adam James
Author by

Adam James

Updated on December 09, 2020

Comments

  • Adam James
    Adam James over 3 years

    I am trying to configure CORS globally via WebMvcConfigurerAdapter shown below. To test I am hitting my API endpoint via a small node app I created to emulate an external service. When I try this approach the response does not contain the correct headers and fails with

    XMLHttpRequest cannot load http://localhost:8080/api/query/1121. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:333' is therefore not allowed access.
    

    Global Config

    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.WebMvcConfigurerAdapter;
    
    @EnableWebMvc
    @Configuration
    public class WebConfig extends WebMvcConfigurerAdapter {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/api/query/**")
                        .allowedOrigins("*")
                        .allowedHeaders("*")
                        .allowCredentials(true);
            }
    }
    

    However when I utilize the @CrossOrigin annotation like so it works just fine responding with the proper headers.

    @CrossOrigin(origins = "*", allowCredentials = "true", allowedHeaders = "*")
    @RestController
    @RequestMapping(value = "/api/query", produces = MediaType.APPLICATION_JSON_VALUE)
    public class QueryController {
       ......
    }
    

    Produces

    Access-Control-Allow-Credentials:true
    Access-Control-Allow-Origin:http://localhost:333
    

    What am I missing to make the global config work (followed instructions here https://spring.io/blog/2015/06/08/cors-support-in-spring-framework). I feel like I'm missing something simple since annotating the controller works just fine.