diff --git a/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java b/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java index 0091168cfa..fe462ce31a 100644 --- a/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java +++ b/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java @@ -338,31 +338,28 @@ public class UriComponentsBuilder implements Cloneable { /** - * Create an instance by parsing the "origin" header of an HTTP request. + * Create an instance by parsing the "Origin" header of an HTTP request. * @see RFC 6454 */ public static UriComponentsBuilder fromOriginHeader(String origin) { - UriComponentsBuilder builder = UriComponentsBuilder.newInstance(); - if (StringUtils.hasText(origin)) { - int schemaIdx = origin.indexOf("://"); - String schema = (schemaIdx != -1 ? origin.substring(0, schemaIdx) : "http"); - builder.scheme(schema); - String hostString = (schemaIdx != -1 ? origin.substring(schemaIdx + 3) : origin); - // Handling of invalid origins as described in SPR-13478 - int firstSlashIdx = hostString.indexOf("/"); - if (firstSlashIdx != -1) { - hostString = hostString.substring(0, firstSlashIdx); + Matcher matcher = URI_PATTERN.matcher(origin); + if (matcher.matches()) { + UriComponentsBuilder builder = new UriComponentsBuilder(); + String scheme = matcher.group(2); + String host = matcher.group(6); + String port = matcher.group(8); + if (StringUtils.hasLength(scheme)) { + builder.scheme(scheme); } - if (hostString.contains(":")) { - String[] hostAndPort = StringUtils.split(hostString, ":"); - builder.host(hostAndPort[0]); - builder.port(Integer.parseInt(hostAndPort[1])); - } - else { - builder.host(hostString); + builder.host(host); + if (StringUtils.hasLength(port)) { + builder.port(port); } + return builder; + } + else { + throw new IllegalArgumentException("[" + origin + "] is not a valid \"Origin\" header value"); } - return builder; } diff --git a/spring-web/src/test/java/org/springframework/web/util/WebUtilsTests.java b/spring-web/src/test/java/org/springframework/web/util/WebUtilsTests.java index 0c0042056b..8f83ea7fb0 100644 --- a/spring-web/src/test/java/org/springframework/web/util/WebUtilsTests.java +++ b/spring-web/src/test/java/org/springframework/web/util/WebUtilsTests.java @@ -142,6 +142,14 @@ public class WebUtilsTests { assertFalse(checkSameOrigin("mydomain2.com", -1, "http://mydomain1.com:80/")); assertFalse(checkSameOrigin("mydomain2.com", -1, "http://mydomain1.com/path")); assertFalse(checkSameOrigin("mydomain2.com", -1, "http://mydomain1.com:80/path")); + + // Handling of IPv6 hosts as described in SPR-13525 + assertTrue(checkSameOrigin("[::1]", -1, "http://[::1]")); + assertTrue(checkSameOrigin("[::1]", 8080, "http://[::1]:8080")); + assertTrue(checkSameOrigin("[2001:0db8:0000:85a3:0000:0000:ac1f:8001]", -1, "http://[2001:0db8:0000:85a3:0000:0000:ac1f:8001]")); + assertTrue(checkSameOrigin("[2001:0db8:0000:85a3:0000:0000:ac1f:8001]", 8080, "http://[2001:0db8:0000:85a3:0000:0000:ac1f:8001]:8080")); + assertFalse(checkSameOrigin("[::1]", -1, "http://[::1]:8080")); + assertFalse(checkSameOrigin("[::1]", 8080, "http://[2001:0db8:0000:85a3:0000:0000:ac1f:8001]:8080")); }