34

I found an example on how to set cors headers in spring-boot application. Since we have many origins, I need to add them. Is the following valid?

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/api/**")
            .allowedOrigins("http://domain1.com")
            .allowedOrigins("http://domain2.com")
            .allowedOrigins("http://domain3.com")
    }
}

I have no way to test this unless it is used by three domains. But I want to make sure I have three origins set up and not only "domain3.com" is set.

EDIT: ideal use case for is to inject a list of domains(from application.properties) and set that in allowedOrigins. Is it possible

i.e

  @Value("${domainsList: not configured}")
    private List<String> domains;

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/api/**")
            .allowedOrigins(domains)
    }
}
brain storm
  • 30,124
  • 69
  • 225
  • 393
  • Can someone look into https://stackoverflow.com/q/59300723/8874958 ? – Kishan Solanki Dec 12 '19 at 08:58
  • See this post answer by miko about Spring supporting wildcards by setAllowedOriginPatterns: https://stackoverflow.com/questions/27147737/cors-filter-allow-all-sub-domains – user2025527 Jan 19 '21 at 11:20

8 Answers8

59

In Spring boot there is an annotation @CrossOrigin which will simply add header in the response.

  1. For multiple:
@CrossOrigin(origins = {"http://localhost:7777", "http://someserver:8080"})
@RequestMapping(value = "/abc", method = RequestMethod.GET)
@ResponseBody
public Object doSomething(){
  ...
}
  1. If you wanna allow for everyone then simply use.
@CrossOrigin
Toni
  • 3,296
  • 2
  • 13
  • 34
Sumit Sundriyal
  • 815
  • 1
  • 11
  • 14
34

The way you are setting will only set the third origin and the other two will be gone.

if you want all the three origins to be set then you need to pass them as comma separated Strings.

@Override
public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/api/**")
        .allowedOrigins("http://domain1.com","http://domain2.com"
                        "http://domain3.com");
}

you can find the actual code here:

https://github.com/spring-projects/spring-framework/blob/00d2606b000f9bdafbd7f4a16b6599fb51b53fa4/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/CorsRegistration.java#L61

https://github.com/spring-projects/spring-framework/blob/31aed61d1543f9f24a82a204309c0afb71dd3912/spring-web/src/main/java/org/springframework/web/cors/CorsConfiguration.java#L122

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
@EnableWebMvc
@PropertySource("classpath:config.properties")
public class CorsClass extends WebMvcConfigurerAdapter {

    @Autowired
    private Environment environment;

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        String origins = environment.getProperty("origins");
        registry.addMapping("/api/**")
                .allowedOrigins(origins.split(","));
    }
}
Deendayal Garg
  • 5,030
  • 2
  • 19
  • 33
4

This would not work, try instead :

registry.addMapping("/api/**")
        .allowedOrigins(
           "http://domain1.com",
           "http://domain2.com",
           "http://domain3.com")

see also spring reference cors

  • how can I pass a list of domains instead of hardcoding here? – brain storm Sep 21 '16 at 19:16
  • @brainstorm Just declare an array of strings (String[] originArray = new Array[] {"http://domain1.com", "http://domain2.com", "http://domain3.com"}) and pass it to .allowedOrigins-Method (...allowedOrigins(originArray) ). – Sercan Samet Savran Sep 07 '20 at 05:32
3

If you're using a Global CORS with Springboot and want to add multiple domains, this is how I've done it:

In your property file, you can add your property and domains as below:

allowed.origins=*.someurl.com,*.otherurl.com,*.someotherurl.com

And your your Config Class:

@EnableWebMvc
@Configuration
public class AppConfig extends WebMvcConfigurerAdapter {

private static final Logger logger = LoggerFactory.getLogger(AppConfig.class);

@Value("#{'${allowed.origins}'.split(',')}")
private List<String> rawOrigins;

@Bean
public RestTemplate restTemplate() {
    return new RestTemplate();
}

@Bean
public WebMvcConfigurer corsConfigurer() {
    return new WebMvcConfigurerAdapter() {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            logger.info("Adding CORS to the service");
            registry.addMapping("/**")
                        .allowedOrigins(getOrigin())
                    .allowedMethods(HttpMethod.GET.name(), HttpMethod.POST.name(), HttpMethod.OPTIONS.name())
                    .allowedHeaders(HttpHeaders.AUTHORIZATION, HttpHeaders.CONTENT_TYPE, "accessToken", "CorrelationId", "source")
                    .exposedHeaders(HttpHeaders.AUTHORIZATION, HttpHeaders.CONTENT_TYPE, "accessToken", "CorrelationId", "source")
                    .maxAge(4800);
        }
         /**
         * This is to add Swagger to work when CORS is enabled
         */
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {

               registry.addResourceHandler("swagger-ui.html")
                        .addResourceLocations("classpath:/META-INF/resources/");

                registry.addResourceHandler("/webjars/**")
                        .addResourceLocations("classpath:/META-INF/resources/webjars/");

        }
    };
}


public String[] getOrigin() {
    int size = rawOrigins.size();
    String[] originArray = new String[size];
    return rawOrigins.toArray(originArray);
}
}

Hope, this helps you and others who are looking for Spring enabled CORS.

2

resources/application.yaml

server:
  port: 8080
  servlet:
    contextPath: /your-service
  jetty:
    acceptors: 1
    maxHttpPostSize: 0
  cors:
    origins:
      - http://localhost:3001
      - https://app.mydomainnnn.com
      - https://app.yourrrrdooomain.com

config/Config.java

package com.service.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.List;

@Configuration
@EnableConfigurationProperties
@ConfigurationProperties("server")
public class Config {

  private int port;
  private Cors cors;

  public int getPort() {
    return this.port;
  }

  public void setPort(int port) {
    this.port = port;
  }

  public Cors getCors() {
    return this.cors;
  }

  public void setCors(Cors cors) {
    this.cors = cors;
  }

  public static class Cors {
    private List<String> origins = new ArrayList<>();

    public List<String> getOrigins() {
      return this.origins;
    }

    public void setOrigins(List<String> origins) {
      this.origins = origins;
    }
  }
}

config/WebConfig.java

package com.service.config;

import java.util.Arrays; 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.core.env.Environment;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.service.controller")
@PropertySource("classpath:application.yaml")
public class WebConfig extends WebMvcConfigurerAdapter {

    @Autowired
    private Environment environment;

    @Autowired
    private Config config;

    @Override
    public void addCorsMappings(CorsRegistry registry) {
      System.out.println("configuring cors");
      String[] origins = config.getCors().getOrigins().toArray(String[]::new);
      System.out.println("  - origins " + Arrays.toString(origins));
      registry.addMapping("/**")
              .allowedOrigins(origins);
    }
}
Onema
  • 7,331
  • 12
  • 66
  • 102
David
  • 3,488
  • 2
  • 21
  • 21
1

Create your custom annotation and annotate the API with that.

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@CrossOrigin
public @interface CrossOriginsList {

    public String[] crossOrigins() default  {

            "http://domain1.com", "http://domain1.com"
            "http://domain1.com", "http://domain1.com"
            // Pass as many as you want
    };
}

And now Annotate your API with this custom Annotation

@CrossOriginsList
    public String methodName() throws Exception
{
        //Business Logic
}

Worked perfectly fine for me.!!

0

This works for me using Springboot 2.7.0

application.yml

allowedOrigins: http://localhost:[*], http://*.your-domain.com:[*]

CorsConfig

@Configuration
public class CorsConfig {


@Value("${allowedOrigins}")
private List<String> domains;

@Bean
public FilterRegistrationBean<CorsFilter> corsFilterRegistrationBean(){
          UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
          CorsConfiguration config = new CorsConfiguration();
          
          // very important to allow patterns !!!
          config.setAllowedOriginPatterns(domains);

          source.registerCorsConfiguration("/**", config); 
          .....
          return new FilterRegistrationBean<>(new CorsFilter(source));
}
0

with spring-security 6, it works for me.

 http.cors().configurationSource(new CorsConfigurationSource() {
        @Override
        public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
            CorsConfiguration config = new CorsConfiguration();
            config.setAllowedOrigins(Collections.singletonList("http://localhost:4200"));
            config.setAllowedMethods(Collections.singletonList("*"));
            config.setAllowCredentials(true);
            config.setAllowedHeaders(Collections.singletonList("*"));
            config.setMaxAge(3600L);
            return config;
        }
Ravi Gupta
  • 81
  • 5