Merge pull request #24680 from pedivo
* gh-24680: Polish "Add config prop for endpoints' CORS allowed origin patterns" Add config prop for endpoints' CORS allowed origin patterns Closes gh-24680
This commit is contained in:
commit
847bb62d69
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2019 the original author or authors.
|
* Copyright 2012-2021 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -37,11 +37,21 @@ import org.springframework.web.cors.CorsConfiguration;
|
||||||
public class CorsEndpointProperties {
|
public class CorsEndpointProperties {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Comma-separated list of origins to allow. '*' allows all origins. When not set,
|
* Comma-separated list of origins to allow. '*' allows all origins. When credentials
|
||||||
* CORS support is disabled.
|
* are allowed, '*' cannot be used and origin patterns should be configured instead.
|
||||||
|
* When no allowed origins or allowed origin patterns are set, CORS support is
|
||||||
|
* disabled.
|
||||||
*/
|
*/
|
||||||
private List<String> allowedOrigins = new ArrayList<>();
|
private List<String> allowedOrigins = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Comma-separated list of origin patterns to allow. Unlike allowed origins which only
|
||||||
|
* supports '*', origin patterns are more flexible (for example
|
||||||
|
* 'https://*.example.com') and can be used when credentials are allowed. When no
|
||||||
|
* allowed origin patterns or allowed origins are set, CORS support is disabled.
|
||||||
|
*/
|
||||||
|
private List<String> allowedOriginPatterns = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Comma-separated list of methods to allow. '*' allows all methods. When not set,
|
* Comma-separated list of methods to allow. '*' allows all methods. When not set,
|
||||||
* defaults to GET.
|
* defaults to GET.
|
||||||
|
|
@ -78,6 +88,14 @@ public class CorsEndpointProperties {
|
||||||
this.allowedOrigins = allowedOrigins;
|
this.allowedOrigins = allowedOrigins;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<String> getAllowedOriginPatterns() {
|
||||||
|
return this.allowedOriginPatterns;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAllowedOriginPatterns(List<String> allowedOriginPatterns) {
|
||||||
|
this.allowedOriginPatterns = allowedOriginPatterns;
|
||||||
|
}
|
||||||
|
|
||||||
public List<String> getAllowedMethods() {
|
public List<String> getAllowedMethods() {
|
||||||
return this.allowedMethods;
|
return this.allowedMethods;
|
||||||
}
|
}
|
||||||
|
|
@ -119,12 +137,13 @@ public class CorsEndpointProperties {
|
||||||
}
|
}
|
||||||
|
|
||||||
public CorsConfiguration toCorsConfiguration() {
|
public CorsConfiguration toCorsConfiguration() {
|
||||||
if (CollectionUtils.isEmpty(this.allowedOrigins)) {
|
if (CollectionUtils.isEmpty(this.allowedOrigins) && CollectionUtils.isEmpty(this.allowedOriginPatterns)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
PropertyMapper map = PropertyMapper.get();
|
PropertyMapper map = PropertyMapper.get();
|
||||||
CorsConfiguration configuration = new CorsConfiguration();
|
CorsConfiguration configuration = new CorsConfiguration();
|
||||||
map.from(this::getAllowedOrigins).to(configuration::setAllowedOrigins);
|
map.from(this::getAllowedOrigins).to(configuration::setAllowedOrigins);
|
||||||
|
map.from(this::getAllowedOriginPatterns).to(configuration::setAllowedOriginPatterns);
|
||||||
map.from(this::getAllowedHeaders).whenNot(CollectionUtils::isEmpty).to(configuration::setAllowedHeaders);
|
map.from(this::getAllowedHeaders).whenNot(CollectionUtils::isEmpty).to(configuration::setAllowedHeaders);
|
||||||
map.from(this::getAllowedMethods).whenNot(CollectionUtils::isEmpty).to(configuration::setAllowedMethods);
|
map.from(this::getAllowedMethods).whenNot(CollectionUtils::isEmpty).to(configuration::setAllowedMethods);
|
||||||
map.from(this::getExposedHeaders).whenNot(CollectionUtils::isEmpty).to(configuration::setExposedHeaders);
|
map.from(this::getExposedHeaders).whenNot(CollectionUtils::isEmpty).to(configuration::setExposedHeaders);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2020 the original author or authors.
|
* Copyright 2012-2021 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -71,6 +71,19 @@ class WebFluxEndpointCorsIntegrationTests {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void settingAllowedOriginPatternsEnablesCors() {
|
||||||
|
this.contextRunner
|
||||||
|
.withPropertyValues("management.endpoints.web.cors.allowed-origin-patterns:*.example.org",
|
||||||
|
"management.endpoints.web.cors.allow-credentials:true")
|
||||||
|
.run(withWebTestClient((webTestClient) -> {
|
||||||
|
webTestClient.options().uri("/actuator/beans").header("Origin", "spring.example.com")
|
||||||
|
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET").exchange().expectStatus()
|
||||||
|
.isForbidden();
|
||||||
|
performAcceptedCorsRequest(webTestClient, "/actuator/beans");
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void maxAgeDefaultsTo30Minutes() {
|
void maxAgeDefaultsTo30Minutes() {
|
||||||
this.contextRunner.withPropertyValues("management.endpoints.web.cors.allowed-origins:spring.example.org")
|
this.contextRunner.withPropertyValues("management.endpoints.web.cors.allowed-origins:spring.example.org")
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2019 the original author or authors.
|
* Copyright 2012-2021 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -77,6 +77,17 @@ class WebMvcEndpointCorsIntegrationTests {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void settingAllowedOriginPatternsEnablesCors() {
|
||||||
|
this.contextRunner.withPropertyValues("management.endpoints.web.cors.allowed-origin-patterns:*.example.com",
|
||||||
|
"management.endpoints.web.cors.allow-credentials:true").run(withMockMvc((mockMvc) -> {
|
||||||
|
mockMvc.perform(options("/actuator/beans").header("Origin", "bar.example.org")
|
||||||
|
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET"))
|
||||||
|
.andExpect(status().isForbidden());
|
||||||
|
performAcceptedCorsRequest(mockMvc);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void maxAgeDefaultsTo30Minutes() {
|
void maxAgeDefaultsTo30Minutes() {
|
||||||
this.contextRunner.withPropertyValues("management.endpoints.web.cors.allowed-origins:foo.example.com")
|
this.contextRunner.withPropertyValues("management.endpoints.web.cors.allowed-origins:foo.example.com")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue