diff --git a/spring-web/src/main/java/org/springframework/web/bind/annotation/CrossOrigin.java b/spring-web/src/main/java/org/springframework/web/bind/annotation/CrossOrigin.java index bb49357aab..ba911a85bb 100644 --- a/spring-web/src/main/java/org/springframework/web/bind/annotation/CrossOrigin.java +++ b/spring-web/src/main/java/org/springframework/web/bind/annotation/CrossOrigin.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -87,9 +87,9 @@ public @interface CrossOrigin { String[] origins() default {}; /** - * Alternative to {@link #origins()} that supports origins declared via - * wildcard patterns. Please, see - * @link CorsConfiguration#setAllowedOriginPatterns(List)} for details. + * Alternative to {@link #origins()} that supports more flexible origins + * patterns. Please, see @link CorsConfiguration#setAllowedOriginPatterns(List)} + * for details. *

By default this is not set. * @since 5.3 */ diff --git a/spring-web/src/main/java/org/springframework/web/cors/CorsConfiguration.java b/spring-web/src/main/java/org/springframework/web/cors/CorsConfiguration.java index 561aa26b7e..1ef8d15f97 100644 --- a/spring-web/src/main/java/org/springframework/web/cors/CorsConfiguration.java +++ b/spring-web/src/main/java/org/springframework/web/cors/CorsConfiguration.java @@ -170,16 +170,22 @@ public class CorsConfiguration { } /** - * Alternative to {@link #setAllowedOrigins} that supports origins declared - * via wildcard patterns. In contrast to {@link #setAllowedOrigins allowedOrigins} - * which does support the special value {@code "*"}, this property allows - * more flexible patterns, e.g. {@code "https://*.domain1.com"}. Furthermore - * it always sets the {@code Access-Control-Allow-Origin} response header to - * the matched origin and never to {@code "*"}, nor to any other pattern, and - * therefore can be used in combination with {@link #setAllowCredentials} - * set to {@code true}. Patterns also support list of allowed ports for origin, - * e.g. {@code "https://*.domain1.com:[8080,8081]"}. Additionally wildcard is supported - * in case any generic port should be allowed {@code "https://*.domain1.com:[*]"}. + * Alternative to {@link #setAllowedOrigins} that supports more flexible + * origins patterns with "*" anywhere in the host name in addition to port + * lists. Examples: + *

+ *

In contrast to {@link #setAllowedOrigins(List) allowedOrigins} which + * only supports "*" and cannot be used with {@code allowCredentials}, when + * an allowedOriginPattern is matched, the {@code Access-Control-Allow-Origin} + * response header is set to the matched origin and not to {@code "*"} nor + * to the pattern. Therefore allowedOriginPatterns can be used in combination + * with {@link #setAllowCredentials} set to {@code true}. *

By default this is not set. * @since 5.3 */ @@ -650,7 +656,7 @@ public class CorsConfiguration { */ private static class OriginPattern { - private static final Pattern PORT_LIST_PATTERN = Pattern.compile("(.*):\\[(\\*|[\\d,]+)]"); + private static final Pattern PORTS_PATTERN = Pattern.compile("(.*):\\[(\\*|\\d+(,\\d+)*)]"); private final String declaredPattern; @@ -658,13 +664,12 @@ public class CorsConfiguration { OriginPattern(String declaredPattern) { this.declaredPattern = declaredPattern; - this.pattern = toPattern(declaredPattern); + this.pattern = initPattern(declaredPattern); } - private static Pattern toPattern(String patternValue) { - //if pattern ends with allowed ports list - Matcher matcher = PORT_LIST_PATTERN.matcher(patternValue); + private static Pattern initPattern(String patternValue) { String portList = null; + Matcher matcher = PORTS_PATTERN.matcher(patternValue); if (matcher.matches()) { patternValue = matcher.group(1); portList = matcher.group(2); @@ -673,12 +678,8 @@ public class CorsConfiguration { patternValue = "\\Q" + patternValue + "\\E"; patternValue = patternValue.replace("*", "\\E.*\\Q"); - if (ALL.equals(portList)) { - //there is a corner case. If '*' is specified, then origins with implicit default port (e.g. "https://test.com") should also match. - patternValue += "(:\\d+)?"; - } - else if (portList != null) { - patternValue += ":(" + portList.replace(',', '|') + ")"; + if (portList != null) { + patternValue += (portList.equals(ALL) ? "(:\\d+)?" : ":(" + portList.replace(',', '|') + ")"); } return Pattern.compile(patternValue);