CORS and It’Configurations in Spring Boot Rest Service


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”

Leave a Reply

Your email address will not be published. Required fields are marked *

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