Thursday, June 9, 2016

Spring boot - is it possible to have Global Cors Configuration using only application.properties?

No, not for Spring Boot 1.3.1.RELEASE at least.

I have a Spring Boot backend application, and an AngularJS front-end application; they run on application servers on different ports (front end on port 3000, backend on port 8443). Because of this, the spring boot application needed to support CORS.

OLD
I originally had the application set up with Global CORS configuration, similar to the following.  All REST endpoints, HTTP GET/PUT/POST supported, with localhost port 3000 as the allowed Origin.

public class CherryShoeApplication {
    public static void main(String[] args) {
        SpringApplication.run(CherryShoeApplication.class, args);
    }
    
    /*
     * Since spring boot 1.3, Global CORS configuration can be defined by registering 
     * a WebMvcConfigurer bean with a customized addCorsMappings(CorsRegistry) method
     */
     @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**")
                .allowedMethods("GET", "PUT", "POST")
                .allowedOrigins("http://localhost:3000")
                ;
             }
         };
    }
}

Needed to update the WebSecurityConfig to allow all HTTP OPTIONS through.  Spring Security pre-authorization was used to protect the application, in this particular example.

public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilterBefore(ssoFilter(),
        RequestHeaderAuthenticationFilter.class)
        .authenticationProvider(preauthAuthProvider()).csrf().disable()
        .authorizeRequests()
        .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() // allow CORS OPTIONS calls through
        .anyRequest().authenticated();
    }
}

NEW
I wanted to move Global CORS configuration out of the Java Config and into application.properties, so it'd be easier to update without a code update.

The same Java Config above (public WebMvcConfigurer corsConfigurer()) is now configured as the following in application.properties:

# ENDPOINTS CORS CONFIGURATION (EndpointCorsProperties)
# Set whether credentials are supported. When not set, credentials are not supported.
endpoints.cors.allow-credentials=false
# Comma-separated list of headers to allow in a request. '*' allows all headers.
endpoints.cors.allowed-headers=*
# Comma-separated list of methods to allow. '*' allows all methods.
endpoints.cors.allowed-methods=GET,PUT,POST
# Comma-separated list of origins to allow. '*' allows all origins. When not set, CORS support is disabled.
endpoints.cors.allowed-origins=http://localhost:3000
# Comma-separated list of extra headers to include in a response, these get exposed by default 
# Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, Pragma
#endpoints.cors.exposed-headers=
# How long, in seconds, the response from a pre-flight request can be cached by clients. 
#endpoints.cors.max-age=1800 

Key takeaway:
There was no way to do a global cors configuration via essentially an "empty" WebMvcConfigurer corsConfigurer (In other words, completely removing the WebMvcConfigurer corsConfigurer @Bean/method), and then use only the application.properties to configure it.  To get the application.properties cors parameters recognized, the @CrossOrigin annotation also needs to be added to each controller. I decided to create a base class and have each controller extend it, so it'd be easier to maintain in the future.

/**
 * Base class so all controllers can extend this class to inherit the @CrossOrigin annotation
 */
@CrossOrigin
public class CrossOriginController {
    // empty, just need the CrossOrigin annotation
}

If you know of any other way to do a global cors configuration using application.propeties cors parameters, please let me know!

5 comments:

  1. You did point out one item that I found interesting: I hadn't found anything that said that the @CrossOrigin notation was required for the application.properties to take effect. I did notice that I could just add the notation, with nothing in the properties file and everything worked. And, if I didn't use the notation, and only used the properties file, the user did receive CORS errors.

    ReplyDelete
  2. refer here: http://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-endpoints.html

    springboot support 2 properties for CORS support:

    endpoints.cors.allowed-origins=http://example.com
    endpoints.cors.allowed-methods=GET,POST

    ReplyDelete
    Replies
    1. Key point for this article was:

      There was no way to do a global cors configuration via essentially an "empty" WebMvcConfigurer corsConfigurer, and then use the application.properties to configure it. To get the application.properties cors parameters recognized, the @CrossOrigin annotation needs to be added to each controller. I decided to create a base class and have each controller extend it, so it'd be easier to maintain in the fugure.

      Delete
  3. Expected to form you a next to no word to thank you once more with respect to the decent recommendations you've contributed here. Those guidelines additionally worked to become a good way to recognize that other people online have the identical fervor like mine to grasp great deal more around this condition. We are providing AngularJs training in velachry.
    For more details: AngularJs training in velachery

    ReplyDelete
  4. I recently found many useful information in your website especially this blog page. Among the lots of comments on your articles. Thanks for sharing. Affinity at serangoon price

    ReplyDelete

I appreciate your time in leaving a comment!