Cross-Origin Resource Sharing known as CORS is an HTTP header-based mechanism that allows a web server to tell the web browser that requests for the current resource is from different origin (URL which may be different schemes like HTTP, HTTPS, header, port, or domain.
CORS also depends upon a mechanism known as preflight in which a web browser sends one OPTION request to the web server in case of a different origin and the server responds with all required details like allowed origins, methods, etc.
In the case of cross-origin, the web browser sends a preflight request and the server sends allowed methods, and origins in response, which is used by a web browser to determine whether the request needs to be sent or blocked. You can see request logs in the chrome network console as shown below.
For example, in the case of different Origine, a web browser will request a server if it would allow a DELETE request, before sending a DELETE request, by using a preflight request:
OPTIONS /resource/foo
Access-Control-Request-Method: DELETE
Access-Control-Request-Headers: origin, x-requested-with
Origin: https://foo.code4copy.com
If the server allows it, then it will respond to the preflight request with an Access-Control-Allow-Methods response header, which lists DELETE:
HTTP/1.1 204 No Content
Connection: keep-alive
Access-Control-Allow-Origin: https://foo.code4copy.com
Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE
Access-Control-Max-Age: 86400
For more details on CORS check here Cross-Origin Resource Sharing (CORS) – HTTP | MDN (mozilla.org)
CORS Configuration in Spring Boot
For CORS implementation Spring Security provides interfaces and classes that can be used to define configuration very easily and quickly. The first and best place is to define one @Configuration
class with all details as given below.
For this, you need to include spring security lib or starter lib in your project.
Gradle Example:
implementation 'org.springframework.boot:spring-boot-starter-security'
Spring security config example
In this example, you need to enable Spring security using @EnableWebSecurity
and using WebSecurityCustomizer
.
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public CorsConfigurationSource corsConfigurationSource(){
CorsConfiguration corsConfiguration = new CorsConfiguration();
// Below config will allow only following origines from web browser
corsConfiguration.setAllowedOrigins(Arrays.asList("code4copy.com", "https://abc.org",
"http://xyz.com", "http://localhost:8080"));
// Whether user credentials are supported. By default, do not support
// If you want to allow credentials then set it true
corsConfiguration.setAllowCredentials(false);
// below will not allow DELETE methods, if you want then add DELETE also
corsConfiguration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH", "OPTION"));
// Below will set allowed headers list, Other headers will not be supported
corsConfiguration.setAllowedHeaders(Arrays.asList("accept", "authorization", "apikey", "tenantId"));
UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
// This will register above configurations on all resources from the root
// If you want different rules for different resources then create separate configuration
// and register on separate resource path uri
corsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
return corsConfigurationSource;
}
@Bean
public FilterRegistrationBean corsFilterRegistrationBean(CorsConfigurationSource corsConfigurationSource){
CorsFilter corsFilter = new CorsFilter(corsConfigurationSource);
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
filterRegistrationBean.setFilter(corsFilter);
return filterRegistrationBean;
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// Here configure all security stuff
http.authorizeRequests().anyRequest().permitAll()
.and().cors(); // .crs().disable() to disable cors
http.headers().frameOptions().sameOrigin();
return http.build();
}
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
// Ignore resources for any check
return (web) -> web.ignoring().antMatchers("/images/**", "/js/**", "/webjars/**");
}
}
In this example, you need to enable Spring security using @EnableWebSecurity
and extending the WebSecurityConfigurerAdapter
interface (Now deprecated, but mostly used in old projects).
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public CorsConfigurationSource corsConfigurationSource(){
CorsConfiguration corsConfiguration = new CorsConfiguration();
// Below config will allow only following origines from web browser
corsConfiguration.setAllowedOrigins(Arrays.asList("code4copy.com", "https://abc.org",
"http://xyz.com", "http://localhost:8080"));
// Whether user credentials are supported. By default, do not support
// If you want to allow credentials then set it true
corsConfiguration.setAllowCredentials(false);
// below will not allow DELETE methods, if you want then add DELETE also
corsConfiguration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH", "OPTION"));
// Below will set allowed headers list, Other headers will not be supported
corsConfiguration.setAllowedHeaders(Arrays.asList("accept", "authorization", "apikey", "tenantId"));
UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
// This will register above configurations on all resources from the root
// If you want different rules for different resources then create separate configuration
// and register on separate resource path uri
corsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
return corsConfigurationSource;
}
@Bean
public FilterRegistrationBean corsFilterRegistrationBean(CorsConfigurationSource corsConfigurationSource){
CorsFilter corsFilter = new CorsFilter(corsConfigurationSource);
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
filterRegistrationBean.setFilter(corsFilter);
return filterRegistrationBean;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().permitAll().and().cors();
}
}
How to check the Request with CORS?
Add one controller in the project as given below.
@Controller
public class TestController {
@GetMapping("/test/")
public ResponseEntity<?> sayHello(){
return new ResponseEntity<>("Hello", HttpStatus.OK);
}
}
Now run your project on the local host and test with curl. If you are on windows then you can download and use curl windows.
C:\Users\bimbi\IdeaProjects\spring-boot-examples>curl -H "Origin: https://abc.org" http://localhost:8080/test/ -X OPTIONS -I
HTTP/1.1 200
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: https://abc.org
Allow: GET,HEAD,OPTIONS
Accept-Patch:
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: SAMEORIGIN
Content-Length: 0
Date: Sat, 23 Jul 2022 14:38:21 GMT
C:\Users\bimbi\IdeaProjects\spring-boot-examples>curl -H "Origin: https://example.reqbin.com" http://localhost:8080/test/
Invalid CORS request
C:\Users\bimbi\IdeaProjects\spring-boot-examples>curl -H "Origin: https://abc.orgm" http://localhost:8080/test/
Invalid CORS request
C:\Users\bimbi\IdeaProjects\spring-boot-examples>curl -H "Origin: https://abc.org" http://localhost:8080/test/
Hello
C:\Users\bimbi\IdeaProjects\spring-boot-examples>
Other methods to use CORS in Spring Boot
The above config will configure CORS rules for a complete application, optionally you can do this for individual API(s) using @CrossOrigin annotation, you can apply it on the entire controller or on individual methods. Note this will work when the global config is not present or the individual path is not configured by corsConfigurationSource.registerCorsConfiguration
.
@Controller
public class TestController {
@GetMapping("/test/")
@CrossOrigin(origins = "https://abc.orgm")
public ResponseEntity<?> sayHello(){
return new ResponseEntity<>("Hello", HttpStatus.OK);
}
}
The above code will apply CORS for origin “https://abc.orgm”.
Can find the complete source at spring-boot-examples/restexample at main · sheelprabhakar/spring-boot-examples (github.com)
One response to “CORS and It’Configurations in Spring Boot Rest Service”
Thanks Buddy you saved my time 🙂