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.
- methods
- exposedHeader
- maxAge
- origins
- 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:
- By default
@CrossOrigin
allows all origins. - 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");
}
}
[pullquote align=”normal”]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 [/pullquote]
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.
Regarding the last example: FilterRegistrationBean expect in the constructor, but UrlBasedCorsConfigurationSource does not implement Filter interface. Am I miss something?
That is a good catch Dima, I have updated the example with following corrections
Return type corrected for corsFilter example.
Updated the constructor arguments.