Spring Boot CORS Configuration Examples

Spring CORS helps in serving web content from multiple domains into browsers who usually have the same-origin security policy. In this example, we will learn to enable CORS support in Spring MVC application at method and global level.

Spring CORS Configuration

CORS (Cross-Origin Resource Sharing) is a browser mechanism that enforces the ‘same-origin‘ policy to protect web applications from potential security threats. When used, CORS allows a webpage to request additional resources into the browser from other domains, such as API data using AJAX, font files, style sheets etc.

We need CORS because modern browsers usually have the same-origin security policy (browsers prohibit AJAX calls to resources outside the current origin). If a cross-origin request violates the same-origin policy and is not permitted by the server’s CORS headers, the browser blocks the request and triggers a CORS error in JavaScript.

In this tutorial, we will learn to enable CORS support in Spring Boot applications at the method level as well as at the global level.

See Also: Creating a CORS Filter using javax.servlet.Filter

1. Different Ways to Apply CORS in Spring Boot?

There are typically the following three ways to apply the CORS on a Spring Boot application:

  1. Using @CrossOrigin annotation at @Controller class and method level. It allows controlling the CORS configuration at the “method level”.
  2. Overriding CorsRegistry on WebMvcConfigurer bean. It allows the definition of the CORS configuration at the “global level” and applies to methods from multiple controllers using the path patterns.
  3. Configure the CORS settings using Spring security’s http.cors() method.

Let us learn each method in detail.

2. Method Level CORS with @CrossOrigin

2.1. @CrossOrigin Annotation

Spring MVC provides @CrossOrigin annotation that marks the annotated method or type as permitting cross-origin requests.

@CrossOrigin
@GetMapping("/{id}")
public Record retrieve(@PathVariable Long id) { ... }

By default, @CrossOrigin allows:

  • all origins
  • all headers
  • all HTTP methods specified in the @RequestMapping annotation
  • maxAge of 30 minutes

To customize the behavior, the annotation supports the following attributes:

  • origins: list of allowed origins. Its value is placed in the Access-Control-Allow-Origin header of both pre-flight and actual responses. The“*” or undefined (default) means that all origins are allowed.
  • allowedHeaders: list of request headers that can be used during the actual request. Its value is used in the preflight’s Access-Control-Allow-Headers response header. The “*” or undefined (default) means that all headers requested by the client are allowed.
  • methods: list of supported HTTP request methods. If undefined (default), methods defined by @RequestMapping are used.
  • exposedHeaders: list of response headers that the browser will allow the client to access. By default, it is an empty list.
  • allowCredentials: determines whether the browser should include any cookies associated with the request. By default, credentials are allowed.
  • maxAge: refers to the maximum age (in seconds) of the cache duration for the pre-flight response’s Access-Control-Max-Age header. The default is 1800 seconds or 30 minutes.
@CrossOrigin(origins = "*", allowedHeaders = "*")

2.2. @CrossOrigin on Controller Class

When applied on the @Controller class top, CORS configuration is applied to each handler method in that class.

In the following example, CORS configuration is applicable to both handler methods.

@CrossOrigin(origins = "*", allowedHeaders = "*")
@RestController("/records")
public class HomeController {

  @GetMapping("/{id}")  
  public Record retrieve(@PathVariable Long id) { ... }

  @PostMapping("/")  
  public ResponseEntity create(@RequestBody Record record) { ... }
}

2.2. @CrossOrigin on Controller Class and Handler Method

We can apply the CORS config at the class level and method level as well. When applied in both places, configuration at the method level takes priority.

@CrossOrigin(origins = "*", allowedHeaders = "*")
@RestController("/records")
public class HomeController {

  @GetMapping("/{id}")  
  @CrossOrigin(origins = "*")
  public Record retrieve(@PathVariable Long id) { ... }

  //...
}

3. Global CORS Configuration with CorsRegistry

To avoid repeating the same configuration over each handler method, we can configure some of the CORS configurations at the global level and then set URL-based CorsConfiguration mappings individually on any handler method.

By default, global configuration enables the following:

  • All origins.
  • All headers.
  • GETHEAD, and POST methods.
  • maxAge set to 30 minutes.

3.1. Using CorsRegistry Callback

To enable CORS for the whole application, use WebMvcConfigurer to add CorsRegistry.

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

  @Override
  public void addCorsMappings(CorsRegistry registry) {

    registry.addMapping("/api/**")
      .allowedOrigins("https://example.com")
      .allowedMethods("GET", "POST")
      .allowedHeaders("header1", "header2", "header3")
      .exposedHeaders("header1", "header2")
      .allowCredentials(true).maxAge(3600);

    // Add more mappings...
  }
}

3.2. Using WebMvcConfigurer Bean

In the Spring boot applications, it is recommended to just declare a WebMvcConfigurer bean.

@Configuration
public class WebConfig
{
    @Bean
    public WebMvcConfigurer corsConfigurer()
    {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**").allowedOrigins("http://localhost:8080");
            }
        };
    }
}

4. CORS with Spring Security

To enable default CORS support through Spring security, use HttpSecurity.cors() method.

@EnableWebSecurity
public class WebSecurityConfig {

  @Bean
  public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.cors().and()...
    //other config
  }
}
@EnableWebSecurity
public class WebSecurityConfig {

  @Bean
  public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
      http.cors().and()...
      //other config
  }
}

To customize the CORS settings, we can supply the CorsConfigurationSource bean as follows:

@EnableWebSecurity
public class WebSecurityConfig {

	//...

	@Bean
	CorsConfigurationSource corsConfigurationSource() {

		CorsConfiguration configuration = new CorsConfiguration();
		configuration.setAllowedOrigins(Arrays.asList("https://example.com"));
		configuration.setAllowedMethods(Arrays.asList("GET","POST"));
		UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
		source.registerCorsConfiguration("/**", configuration);
		return source;
	}
}

Drop me your questions in the comments section.

Happy Learning !!

Sourcecode on Github

Leave a Comment

  1. This is really great. Exactly what I was looking for. Unfortunately, It did not work for what I am working on. I am attempting to implement SOAP using Spring Boot, and when I try and grab the WSDL from my angular project, I get A CORS Policy violation. The WSDL is generated automatically by Spring Boot and made available as an endpoint by a MessageDispatcherServlet:

    package com.rioh.endpoints.configuration;
    
    import org.springframework.boot.web.servlet.ServletRegistrationBean;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.io.ClassPathResource;
    import org.springframework.web.bind.annotation.CrossOrigin;
    import org.springframework.web.servlet.config.annotation.CorsRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    import org.springframework.ws.config.annotation.EnableWs;
    import org.springframework.ws.transport.http.MessageDispatcherServlet;
    import org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition;
    import org.springframework.xml.xsd.SimpleXsdSchema;
    import org.springframework.xml.xsd.XsdSchema;
    
    @Configuration
    @EnableWs
    public class RoutesEndpointConfig
    {
    
    	@Bean
    	public ServletRegistrationBean messageDispatcherServlet(ApplicationContext context)
    	{
    		MessageDispatcherServlet servlet = new MessageDispatcherServlet();
    		servlet.setApplicationContext(context);
    		servlet.setTransformWsdlLocations(true); 
    		return new ServletRegistrationBean(servlet, "/ws/*");
    	}
    	@Bean(name = "Routes")
    	public DefaultWsdl11Definition defaultWsdl11DefinitionAddRoute(XsdSchema schema)
    	{
    		DefaultWsdl11Definition defaultWsdl11Definition = new DefaultWsdl11Definition();
    		defaultWsdl11Definition.setPortTypeName("Routes");
    		defaultWsdl11Definition.setLocationUri("/ws");
    		defaultWsdl11Definition.setTargetNamespace("http://www.rioh.Route.webservice");
    		defaultWsdl11Definition.setSchema(schema);
    		return defaultWsdl11Definition;
    	}
    	
    	@Bean
    	public XsdSchema schema()
    	{
    		return new SimpleXsdSchema(new ClassPathResource("RouteSoapMeta.xsd"));
    	}
    	
    }
    

    Even when using the global CORS configuration, I still get the “Blocked by cors policy” error in my browser when I try and access it from my angular project.

    Reply
  2. “WebSecurityConfigurerAdapter”

    Have you tested this code.

    WebSecurityConfigurerAdapter is deprecated with Spring 5 and Spring Boot 2.0.

    Adifferent appraoch has to be used.

    Reply
  3. Somehow every code base on Spring Boot 2 Security including the examples on “Spring.io” work only on localhost.

    Looks like there is some undocumented code base related to CORS. Because the document approach fails in staging hence cannot be enhanced and promoted to production.

    None work in Production or staging environment.

    I have tested this code base and various others on code bases on AWS, Azure, Google and other cloud vendors.

    Somehow all sample code-bases work excellently on local host.

    On staging it is failure.

    I have tried two scenarios the application front-end on a different physical instance on Apache httpd and java Rest Services on a different physical instance with Tomcat.

    Reply
  4. Hi,

    I’m trying you integrate angular js with spring boot. I’m getting cross origin error at angular js side after the call returns from rest service. Will this snippet add header to the response? It seems it’s not working in my code.

    thanks,
    jayapriya

    Reply
  5. Hi, greate example and it works perfect, but I have updated my code base to spring 5 and spring boot 2 and that code is shown as deprecated. I have modified the implementation and all works fine but i have a problem when a the originating request is coming from a domain bound to a port like localhost:3001 (example

    Reply
  6. Hi thanks for your valuable example, i have enables cors for spring security in XML, but i am getting 401 unauthorised problem of preflight request with OPTIONS method. I am using spring security and wildfly server.

    Reply

Leave a Comment

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.