Spring Boot CORS

Updated on October 1st, 2019

In this post of Spring Boot, we will look at the Spring Boot CORS support.

 

Introduction

CORS (Cross-origin resource sharing)  allows a webpage to request additional resources into browser from other domains e.g. fonts, CSS or static images from CDNs. CORS is a W3C specification which provides options for the CORS request. Spring 4.2+ provides build in support to for the Cross-origin resource sharing. In this post we will take a closer at the Spring Boot CORS support and how to enable it for your application.

 

1. Controller Method

To enable the CORS for your Spring or Spring Boot application, add the @CrossOrigin annotation in the controller. There are several ways to add this annotation in your controller class. Let’s look at some examples for better clarity:

 

1.1. @CrossOrigin Controller Level

To enable the Spring CORS support for the entire controller, we can add the annotation at the class level.

@CrossOrigin(origins = "http://external-system.com", maxAge = 3600)
@RestController
@RequestMapping("/products")
public class AccountController {
 
    @GetMapping("/{code}")
    public Product getProduct(@PathVariable String code) {
        // ...
    }
 
    @GetMapping("/reviews")
    public List<ProductReviews> getProductReviews() {
        // ...
    }
}

In this example, Spring cors support is enable for all the method in the controller (in our case both getProduct() and getProductReviews() method). To customize the behaviour of the @CrossOrigin annotation, we can specify the values for the following annotation attributes.

  1. methods
  2. exposedHeader
  3. maxAge
  4. origins
  5. allowedHeader

 

1.2. Annotation At Method Level

We have the option to add the @CrossOrigin annotation at the method level.

@RestController
@RequestMapping("/products")
public class AccountController {
    
    @CrossOrigin
    @GetMapping("/{code}")
    public Product getProduct(@PathVariable String code) {
        // ...
    }
 
    @GetMapping("/reviews")
    public List<ProductReviews> getProductReviews() {
        // ...
    }
}

While working on this, let’s keep in mind following important points:

  1. By default @CrossOrigin allows all origins.
  2. The default maxAge is 30 minutes.

 

1.3. Combining Controller and Method Level

We can also use this annotation at both controller and method level. Spring will combine both configuration to create a merged CORS configuration:

@CrossOrigin(maxAge = 3600)
@RestController
@RequestMapping("/products")
public class AccountController {
    
    @CrossOrigin(origins = "http://external-system.com")
    @GetMapping("/{code}")
    public Product getProduct(@PathVariable String code) {
        // ...
    }
 
    @GetMapping("/reviews")
    public List<ProductReviews> getProductReviews() {
        // ...
    }
}

You can use this to override the configuration at the method level. Let’s take the following example to see this in action:

@CrossOrigin(origins =*, maxAge = 3600)
@RestController
@RequestMapping("/products")
public class AccountController {
    
    @CrossOrigin(origins = "http://external-system.com")
    @GetMapping("/{code}")
    public Product getProduct(@PathVariable String code) {
        // ...
    }
 
    @GetMapping("/reviews")
    public List<ProductReviews> getProductReviews() {
        // ...
    }
}

 

2. Global CORS configurations

Spring CORS also provides an option to define global CORS configurations. You can think this approach similar to creating filters but can be declared withing Spring MVC and combined with fine-grained @CrossOrigin configuration.

 

2.1. Java Configuration

To enable the global CORS configuration in your Spring Boot application, we can declare a WebMvcConfigurer bean

@Configuration
public class CorsConfiguration
{
    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/rest/v2//**").allowedMethods("PUT", "DELETE");
            }
        };
    }
}

For Spring MVC application:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/rest/v2/**").allowedMethods("PUT", "DELETE");
    }
}

If you are using Spring Security, enable CORS at Spring Security level as well to allow it to leverage the configuration defined at Spring MVC level

 

3. Spring CORS using Filter

To handle the CORS, Spring also provide a CorsFilter which is an alternate to the approach defined in the first section of this post.

@Bean
public FilterRegistrationBean corsFilter() {
    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    final CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.setAllowedOrigins(Collections.singletonList("http://sample-domain.com"));
    config.setAllowedHeaders(Arrays.asList("Origin", "Content-Type", "Accept"));
    config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "OPTIONS", "DELETE", "PATCH"));
    source.registerCorsConfiguration("/**", config);
    FilterRegistrationBean registration = new FilterRegistrationBean(new CorsFilter(source));
    return registration;
}

 

Summary

In this post, we leaned about the Spring Boot CORS support. We saw how to use the @CrossOrigin annotation at Controller and method level and how to override the configurations. At the end of the post we saw how to enable the global cors configuration and implement the cors using a filter.

2
Leave a Reply

avatar
1 Comment threads
1 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
2 Comment authors
Umesh AwasthiDima Recent comment authors

This site uses Akismet to reduce spam. Learn how your comment data is processed.

  Subscribe  
newest oldest most voted
Notify of
Dima
Guest
Dima

Regarding the last example: FilterRegistrationBean expect in the constructor, but UrlBasedCorsConfigurationSource does not implement Filter interface. Am I miss something?

Umesh Awasthi
Admin
Umesh Awasthi

That is a good catch Dima, I have updated the example with following corrections

    Return type corrected for corsFilter example.
    Updated the constructor arguments.