Updates to CORS patterns contribution

Closes gh-25016
This commit is contained in:
Rossen Stoyanchev
2020-07-08 13:18:11 +03:00
parent 1181bb1852
commit 0e4e25d227
24 changed files with 488 additions and 256 deletions

View File

@@ -60,6 +60,10 @@ public class CorsBeanDefinitionParser implements BeanDefinitionParser {
String[] allowedOrigins = StringUtils.tokenizeToStringArray(mapping.getAttribute("allowed-origins"), ",");
config.setAllowedOrigins(Arrays.asList(allowedOrigins));
}
if (mapping.hasAttribute("allowed-origin-patterns")) {
String[] patterns = StringUtils.tokenizeToStringArray(mapping.getAttribute("allowed-origin-patterns"), ",");
config.setAllowedOriginPatterns(Arrays.asList(patterns));
}
if (mapping.hasAttribute("allowed-methods")) {
String[] allowedMethods = StringUtils.tokenizeToStringArray(mapping.getAttribute("allowed-methods"), ",");
config.setAllowedMethods(Arrays.asList(allowedMethods));
@@ -78,7 +82,9 @@ public class CorsBeanDefinitionParser implements BeanDefinitionParser {
if (mapping.hasAttribute("max-age")) {
config.setMaxAge(Long.parseLong(mapping.getAttribute("max-age")));
}
corsConfigurations.put(mapping.getAttribute("path"), config.applyPermitDefaultValues());
config.applyPermitDefaultValues();
config.validateAllowCredentials();
corsConfigurations.put(mapping.getAttribute("path"), config);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2020 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.
@@ -17,6 +17,7 @@
package org.springframework.web.servlet.config.annotation;
import java.util.Arrays;
import java.util.List;
import org.springframework.web.cors.CorsConfiguration;
@@ -46,24 +47,27 @@ public class CorsRegistration {
/**
* The list of allowed origins that be specific origins, e.g.
* {@code "https://domain1.com"}, or {@code "*"} for all origins.
* <p>A matched origin is listed in the {@code Access-Control-Allow-Origin}
* response header of preflight actual CORS requests.
* <p>By default, all origins are allowed.
* <p><strong>Note:</strong> CORS checks use values from "Forwarded"
* (<a href="https://tools.ietf.org/html/rfc7239">RFC 7239</a>),
* "X-Forwarded-Host", "X-Forwarded-Port", and "X-Forwarded-Proto" headers,
* if present, in order to reflect the client-originated address.
* Consider using the {@code ForwardedHeaderFilter} in order to choose from a
* central place whether to extract and use, or to discard such headers.
* See the Spring Framework reference for more on this filter.
* A list of origins for which cross-origin requests are allowed. Please,
* see {@link CorsConfiguration#setAllowedOrigins(List)} for details.
* <p>By default all origins are allowed unless {@code originPatterns} is
* also set in which case {@code originPatterns} is used instead.
*/
public CorsRegistration allowedOrigins(String... origins) {
this.config.setAllowedOrigins(Arrays.asList(origins));
return this;
}
/**
* Alternative to {@link #allowCredentials} that supports origins declared
* via wildcard patterns. Please, see
* @link CorsConfiguration#setAllowedOriginPatterns(List)} for details.
* <p>By default this is not set.
* @since 5.3
*/
public CorsRegistration allowedOriginPatterns(String... patterns) {
this.config.setAllowedOriginPatterns(Arrays.asList(patterns));
return this;
}
/**
* Set the HTTP methods to allow, e.g. {@code "GET"}, {@code "POST"}, etc.

View File

@@ -516,6 +516,9 @@ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
CorsConfiguration globalConfig = getCorsConfigurationSource().getCorsConfiguration(request);
config = (globalConfig != null ? globalConfig.combine(config) : config);
}
if (config != null) {
config.validateAllowCredentials();
}
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}

View File

@@ -86,7 +86,7 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
private static final CorsConfiguration ALLOW_CORS_CONFIG = new CorsConfiguration();
static {
ALLOW_CORS_CONFIG.addAllowedOrigin("*");
ALLOW_CORS_CONFIG.addAllowedOriginPattern("*");
ALLOW_CORS_CONFIG.addAllowedMethod("*");
ALLOW_CORS_CONFIG.addAllowedHeader("*");
ALLOW_CORS_CONFIG.setAllowCredentials(true);
@@ -630,9 +630,10 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
addMappingName(name, handlerMethod);
}
CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
if (corsConfig != null) {
this.corsLookup.put(handlerMethod, corsConfig);
CorsConfiguration config = initCorsConfiguration(handler, method, mapping);
if (config != null) {
config.validateAllowCredentials();
this.corsLookup.put(handlerMethod, config);
}
this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directUrls, name));

View File

@@ -1346,6 +1346,15 @@
Comma-separated list of origins to allow, e.g. "https://domain1.com, https://domain2.com".
The special value "*" allows all domains (default).
For matching pre-flight and actual requests the "Access-Control-Allow-Origin"
response header is set either to the matched domain value or to "*".
Keep in mind however that the CORS spec does not allow "*" when allow-credentials
is set to true and that is rejected as of 5.3. See allowed-origin-patterns for
further options.
By default all origins are allowed unless allowed-origin-patterns is also set
in which case allowed-origin-patterns is used instead.
Note that CORS checks use values from "Forwarded" (RFC 7239), "X-Forwarded-Host",
"X-Forwarded-Port", and "X-Forwarded-Proto" headers, if present, in order to reflect
the client-originated address. Consider using the ForwardedHeaderFilter in order to
@@ -1354,6 +1363,20 @@
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="allowed-origin-patterns" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
Alternative to allowed-origins that supports origins declared via patterns.
In contrast to allowed-origins which does support the special value "*", this
property allows more flexible patterns, e.g. "*.domain1.com". Furthermore it
always sets the "Access-Control-Allow-Origin" response header to the matched
origin and never to "*" nor to any other pattern and therefore can be used in
combination with allowCredentials set to true.
By default this is not set.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="allowed-methods" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[