Search code examples
angularspring-bootcors

Spring Boot Restful Service and CORS problem


I created a Restful service with Spring Boot and I am sending HTTP requests to this service with Angular. I was getting a CORS error when I sent a request with Angular and I used artificial intelligence to solve the error. In the first attempt, it asked me to suggested the following bean.

@Bean
    public WebMvcConfigurer corsConfigurer(){
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**")
                        .allowedOrigins("http://localhost:4200")
                        .allowedMethods("GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS")
                        .allowedHeaders("*")
                        .allowCredentials(true);
            }
        };
    }

Then, when I wanted to export the front-end as live server, I also got CORS error and it suggested me to add the following bean.

@Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedOrigin("http://192.168.5.76:4200");
        config.addAllowedOrigin("http://localhost:4200");
        config.addAllowedMethod("*");
        config.addAllowedHeader("*");
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }

When I did some more research on the internet, I saw that the WebMvcConfigurer structure is recommended. But I don't understand which one I should use in which situation and I couldn't find a detailed explanation. I wonder if there is someone who can provide an explanatory source or explanation on this subject.


Solution

  • Option 1: defining with SecurityFilterChain

    In modern SpringSecurity (Spring Security 6) you can do CORS configuration together with SecurityFilterChain:

    @Configuration
    public class SecurityConfiguration {
    
        @Bean
        public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
            return httpSecurity
                    .cors(c -> {
                        CorsConfigurationSource source = request -> {
                            CorsConfiguration configuration = new CorsConfiguration();
                            configuration.setAllowedOrigins(List.of("http://localhost:4200"));
                            configuration.setAllowedMethods(List.of("GET", "POST"));
                            configuration.setAllowedHeaders(List.of("*"));
                            configuration.setAllowCredentials(true);
                            return configuration;
                        };
                        c.configurationSource(source);
                    })
                    .build();
        }
    }
    

    I noticed that if you try to configure CORS after SecurityFilterChain (somewhere else) that can cause issues since some default configuration has already been configured with SecurityFilterChain


    Option 2: separate CorsConfigurationSource

    That means you could also define CorsConfigurationSource as a separarte bean (instead of doing it with SecurityFilterChain) but then you have to define it with higher precedence:

    @Configuration
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public class CorsConfig {
    
        @Bean
        CorsConfigurationSource corsConfigurationSource() {
            final var configuration = new CorsConfiguration();
            configuration.setAllowedOriginPatterns(List.of("*"));
            configuration.setAllowedMethods(List.of("GET", "POST"));
            configuration.setAllowCredentials(true);
            configuration.setAllowedHeaders(List.of("*"));
            final var source = new UrlBasedCorsConfigurationSource();
            source.registerCorsConfiguration("/**", configuration);
            return source;
        }