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:
Rossen Stoyanchev
2021-05-10 12:02:08 +01:00
parent 07ba95739b
commit dc4e053d59
2 changed files with 17 additions and 4 deletions

View File

@@ -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();

View File

@@ -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");
} }