CorsConfiguration ignores trailing "/" in pattern
Recent commit dddcc5e9ad ensured a
trailing "/" in the Origin header has no effect. This commit does the
same for a trailing "/" in configured patterns.
See gh-26892
This commit is contained in:
@@ -138,7 +138,12 @@ public class CorsConfiguration {
|
|||||||
* {@code @CrossOrigin}, via {@link #applyPermitDefaultValues()}.
|
* {@code @CrossOrigin}, via {@link #applyPermitDefaultValues()}.
|
||||||
*/
|
*/
|
||||||
public void setAllowedOrigins(@Nullable List<String> allowedOrigins) {
|
public void setAllowedOrigins(@Nullable List<String> allowedOrigins) {
|
||||||
this.allowedOrigins = (allowedOrigins != null ? new ArrayList<>(allowedOrigins) : null);
|
this.allowedOrigins = (allowedOrigins != null ?
|
||||||
|
allowedOrigins.stream().map(this::trimTrailingSlash).collect(Collectors.toList()) : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String trimTrailingSlash(String origin) {
|
||||||
|
return origin.endsWith("/") ? origin.substring(0, origin.length() - 1) : origin;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -159,6 +164,7 @@ public class CorsConfiguration {
|
|||||||
else if (this.allowedOrigins == DEFAULT_PERMIT_ALL && CollectionUtils.isEmpty(this.allowedOriginPatterns)) {
|
else if (this.allowedOrigins == DEFAULT_PERMIT_ALL && CollectionUtils.isEmpty(this.allowedOriginPatterns)) {
|
||||||
setAllowedOrigins(DEFAULT_PERMIT_ALL);
|
setAllowedOrigins(DEFAULT_PERMIT_ALL);
|
||||||
}
|
}
|
||||||
|
origin = trimTrailingSlash(origin);
|
||||||
this.allowedOrigins.add(origin);
|
this.allowedOrigins.add(origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,6 +215,7 @@ public class CorsConfiguration {
|
|||||||
if (this.allowedOriginPatterns == null) {
|
if (this.allowedOriginPatterns == null) {
|
||||||
this.allowedOriginPatterns = new ArrayList<>(4);
|
this.allowedOriginPatterns = new ArrayList<>(4);
|
||||||
}
|
}
|
||||||
|
originPattern = trimTrailingSlash(originPattern);
|
||||||
this.allowedOriginPatterns.add(new OriginPattern(originPattern));
|
this.allowedOriginPatterns.add(new OriginPattern(originPattern));
|
||||||
if (this.allowedOrigins == DEFAULT_PERMIT_ALL) {
|
if (this.allowedOrigins == DEFAULT_PERMIT_ALL) {
|
||||||
this.allowedOrigins = null;
|
this.allowedOrigins = null;
|
||||||
@@ -551,9 +558,7 @@ public class CorsConfiguration {
|
|||||||
if (!StringUtils.hasText(requestOrigin)) {
|
if (!StringUtils.hasText(requestOrigin)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (requestOrigin.endsWith("/")) {
|
requestOrigin = trimTrailingSlash(requestOrigin);
|
||||||
requestOrigin = requestOrigin.substring(0, requestOrigin.length() - 1);
|
|
||||||
}
|
|
||||||
if (!ObjectUtils.isEmpty(this.allowedOrigins)) {
|
if (!ObjectUtils.isEmpty(this.allowedOrigins)) {
|
||||||
if (this.allowedOrigins.contains(ALL)) {
|
if (this.allowedOrigins.contains(ALL)) {
|
||||||
validateAllowCredentials();
|
validateAllowCredentials();
|
||||||
|
|||||||
@@ -282,17 +282,25 @@ public class CorsConfigurationTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void checkOriginAllowed() {
|
public void checkOriginAllowed() {
|
||||||
|
// "*" matches
|
||||||
CorsConfiguration config = new CorsConfiguration();
|
CorsConfiguration config = new CorsConfiguration();
|
||||||
config.addAllowedOrigin("*");
|
config.addAllowedOrigin("*");
|
||||||
assertThat(config.checkOrigin("https://domain.com")).isEqualTo("*");
|
assertThat(config.checkOrigin("https://domain.com")).isEqualTo("*");
|
||||||
|
|
||||||
|
// "*" does not match together with allowCredentials
|
||||||
config.setAllowCredentials(true);
|
config.setAllowCredentials(true);
|
||||||
assertThatIllegalArgumentException().isThrownBy(() -> config.checkOrigin("https://domain.com"));
|
assertThatIllegalArgumentException().isThrownBy(() -> config.checkOrigin("https://domain.com"));
|
||||||
|
|
||||||
|
// specific origin matches Origin header with or without trailing "/"
|
||||||
config.setAllowedOrigins(Collections.singletonList("https://domain.com"));
|
config.setAllowedOrigins(Collections.singletonList("https://domain.com"));
|
||||||
assertThat(config.checkOrigin("https://domain.com")).isEqualTo("https://domain.com");
|
assertThat(config.checkOrigin("https://domain.com")).isEqualTo("https://domain.com");
|
||||||
assertThat(config.checkOrigin("https://domain.com/")).isEqualTo("https://domain.com");
|
assertThat(config.checkOrigin("https://domain.com/")).isEqualTo("https://domain.com");
|
||||||
|
|
||||||
|
// specific origin with trailing "/" matches Origin header with or without trailing "/"
|
||||||
|
config.setAllowedOrigins(Collections.singletonList("https://domain.com/"));
|
||||||
|
assertThat(config.checkOrigin("https://domain.com")).isEqualTo("https://domain.com");
|
||||||
|
assertThat(config.checkOrigin("https://domain.com/")).isEqualTo("https://domain.com");
|
||||||
|
|
||||||
config.setAllowCredentials(false);
|
config.setAllowCredentials(false);
|
||||||
assertThat(config.checkOrigin("https://domain.com")).isEqualTo("https://domain.com");
|
assertThat(config.checkOrigin("https://domain.com")).isEqualTo("https://domain.com");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user