Merge branch '6.0.x'

This commit is contained in:
Sébastien Deleuze 2023-09-11 18:10:13 +02:00
commit dfd631e662
8 changed files with 137 additions and 66 deletions

View File

@ -75,6 +75,35 @@ To learn more from the source or to make advanced customizations, see:
[[webflux-cors-credentialed-requests]]
== Credentialed Requests
[.small]#xref:web/webmvc-cors.adoc#mvc-cors-credentialed-requests[See equivalent in the Servlet stack]#
Using CORS with credentialed requests requires enabling `allowedCredentials`. Be aware that
this option establishes a high level of trust with the configured domains and also increases
the surface of attack of the web application by exposing sensitive user-specific information
such as cookies and CSRF tokens.
Enabling credentials also impacts how the configured `"*"` CORS wildcards are processed:
* Wildcards are not authorized in `allowOrigins`, but alternatively
the `allowOriginPatterns` property may be used to match to a dynamic set of origins.
* When set on `allowedHeaders` or `allowedMethods`, the `Access-Control-Allow-Headers`
and `Access-Control-Allow-Methods` response headers are handled by copying the related
headers and method specified in the CORS preflight request.
* When set on `exposedHeaders`, `Access-Control-Expose-Headers` response header is set
either to the configured list of headers or to the wildcard character. While the CORS spec
does not allow the wildcard character when `Access-Control-Allow-Credentials` is set to
`true`, most browsers support it and the response headers are not all available during the
CORS processing, so as a consequence the wildcard character is the header value used when
specified regardless of the value of the `allowCredentials` property.
WARNING: While such wildcard configuration can be handy, it is recommended when possible to configure
a finite set of values instead to provide a higher level of security.
[[webflux-cors-controller]]
== `@CrossOrigin`
[.small]#xref:web/webmvc-cors.adoc#mvc-cors-controller[See equivalent in the Servlet stack]#

View File

@ -25,6 +25,35 @@ powerful workarounds based on IFRAME or JSONP.
[[mvc-cors-credentialed-requests]]
== Credentialed Requests
[.small]#xref:web/webflux-cors.adoc#webflux-cors-credentialed-requests[See equivalent in the Reactive stack]#
Using CORS with credentialed requests requires enabling `allowedCredentials`. Be aware that
this option establishes a high level of trust with the configured domains and also increases
the surface of attack of the web application by exposing sensitive user-specific information
such as cookies and CSRF tokens.
Enabling credentials also impacts how the configured `"*"` CORS wildcards are processed:
* Wildcards are not authorized in `allowOrigins`, but alternatively
the `allowOriginPatterns` property may be used to match to a dynamic set of origins.
* When set on `allowedHeaders` or `allowedMethods`, the `Access-Control-Allow-Headers`
and `Access-Control-Allow-Methods` response headers are handled by copying the related
headers and method specified in the CORS preflight request.
* When set on `exposedHeaders`, `Access-Control-Expose-Headers` response header is set
either to the configured list of headers or to the wildcard character. While the CORS spec
does not allow the wildcard character when `Access-Control-Allow-Credentials` is set to
`true`, most browsers support it and the response headers are not all available during the
CORS processing, so as a consequence the wildcard character is the header value used when
specified regardless of the value of the `allowCredentials` property.
WARNING: While such wildcard configuration can be handy, it is recommended when possible to configure
a finite set of values instead to provide a higher level of security.
[[mvc-cors-processing]]
== Processing
[.small]#xref:web/webflux-cors.adoc#webflux-cors-processing[See equivalent in the Reactive stack]#

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2023 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.
@ -80,31 +80,23 @@ public @interface CrossOrigin {
/**
* The list of request headers that are permitted in actual requests,
* possibly {@code "*"} to allow all headers.
* <p>Allowed headers are listed in the {@code Access-Control-Allow-Headers}
* response header of preflight requests.
* <p>A header name is not required to be listed if it is one of:
* {@code Cache-Control}, {@code Content-Language}, {@code Expires},
* {@code Last-Modified}, or {@code Pragma} as per the CORS spec.
* possibly {@code "*"} to allow all headers. Please, see
* {@link CorsConfiguration#setAllowedHeaders(List)} for details.
* <p>By default all requested headers are allowed.
*/
String[] allowedHeaders() default {};
/**
* The List of response headers that the user-agent will allow the client
* to access on an actual response, other than "simple" headers, i.e.
* {@code Cache-Control}, {@code Content-Language}, {@code Content-Type},
* {@code Expires}, {@code Last-Modified}, or {@code Pragma},
* <p>Exposed headers are listed in the {@code Access-Control-Expose-Headers}
* response header of actual CORS requests.
* <p>The special value {@code "*"} allows all headers to be exposed for
* non-credentialed requests.
* to access on an actual response, possibly {@code "*"} to expose all headers.
* Please, see {@link CorsConfiguration#setExposedHeaders(List)} for details.
* <p>By default no headers are listed as exposed.
*/
String[] exposedHeaders() default {};
/**
* The list of supported HTTP request methods.
* The list of supported HTTP request methods. Please, see
* {@link CorsConfiguration#setAllowedMethods(List)} for details.
* <p>By default the supported methods are the same as the ones to which a
* controller method is mapped.
*/
@ -112,9 +104,8 @@ public @interface CrossOrigin {
/**
* Whether the browser should send credentials, such as cookies along with
* cross domain requests, to the annotated endpoint. The configured value is
* set on the {@code Access-Control-Allow-Credentials} response header of
* preflight requests.
* cross domain requests, to the annotated endpoint. Please, see
* {@link CorsConfiguration#setAllowCredentials(Boolean)} for details.
* <p><strong>NOTE:</strong> Be aware that this option establishes a high
* level of trust with the configured domains and also increases the surface
* attack of the web application by exposing sensitive user-specific

View File

@ -280,8 +280,12 @@ public class CorsConfiguration {
/**
* Set the HTTP methods to allow, e.g. {@code "GET"}, {@code "POST"},
* {@code "PUT"}, etc.
* <p>The special value {@code "*"} allows all methods.
* {@code "PUT"}, etc. The special value {@code "*"} allows all methods.
* <p>{@code Access-Control-Allow-Methods} response header is set either
* to the configured method or to {@code "*"}. Keep in mind however that the
* CORS spec does not allow {@code "*"} when {@link #setAllowCredentials
* allowCredentials} is set to {@code true}, that combination is handled
* by copying the method specified in the CORS preflight request.
* <p>If not set, only {@code "GET"} and {@code "HEAD"} are allowed.
* <p>By default this is not set.
* <p><strong>Note:</strong> CORS checks use values from "Forwarded"
@ -312,9 +316,9 @@ public class CorsConfiguration {
/**
* Return the allowed HTTP methods, or {@code null} in which case
* only {@code "GET"} and {@code "HEAD"} allowed.
* @see #setAllowedMethods(List)
* @see #addAllowedMethod(HttpMethod)
* @see #addAllowedMethod(String)
* @see #setAllowedMethods(List)
*/
@Nullable
public List<String> getAllowedMethods() {
@ -322,14 +326,14 @@ public class CorsConfiguration {
}
/**
* Add an HTTP method to allow.
* Variant of {@link #setAllowedMethods} for adding one allowed method at a time.
*/
public void addAllowedMethod(HttpMethod method) {
addAllowedMethod(method.name());
}
/**
* Add an HTTP method to allow.
* Variant of {@link #setAllowedMethods} for adding one allowed method at a time.
*/
public void addAllowedMethod(String method) {
if (StringUtils.hasText(method)) {
@ -352,9 +356,13 @@ public class CorsConfiguration {
/**
* Set the list of headers that a pre-flight request can list as allowed
* for use during an actual request.
* <p>The special value {@code "*"} allows actual requests to send any
* header.
* for use during an actual request. The special value {@code "*"} allows
* actual requests to send any header.
* <p>{@code Access-Control-Allow-Headers} response header is set either
* to the configured list of headers or to {@code "*"}. Keep in mind however
* that the CORS spec does not allow {@code "*"} when {@link #setAllowCredentials
* allowCredentials} is set to {@code true}, that combination is handled by
* copying the headers specified in the CORS preflight request.
* <p>A header name is not required to be listed if it is one of:
* {@code Cache-Control}, {@code Content-Language}, {@code Expires},
* {@code Last-Modified}, or {@code Pragma}.
@ -375,7 +383,7 @@ public class CorsConfiguration {
}
/**
* Add an actual request header to allow.
* Variant of {@link #setAllowedHeaders(List)} for adding one allowed header at a time.
*/
public void addAllowedHeader(String allowedHeader) {
if (this.allowedHeaders == null) {
@ -388,12 +396,19 @@ public class CorsConfiguration {
}
/**
* Set the list of response headers other than simple headers (i.e.
* {@code Cache-Control}, {@code Content-Language}, {@code Content-Type},
* {@code Expires}, {@code Last-Modified}, or {@code Pragma}) that an
* actual response might have and can be exposed.
* <p>The special value {@code "*"} allows all headers to be exposed for
* non-credentialed requests.
* Set the list of response headers that an actual response might have
* and can be exposed to the client. The special value {@code "*"}
* allows all headers to be exposed.
* <p>{@code Access-Control-Expose-Headers} response header is set either
* to the configured list of headers or to {@code "*"}. While the CORS
* spec does not allow {@code "*"} when {@code Access-Control-Allow-Credentials}
* is set to {@code true}, most browsers support it and
* the response headers are not all available during the CORS processing,
* so as a consequence {@code "*"} is the header value used when specified
* regardless of the value of the `allowCredentials` property.
* <p>A header name is not required to be listed if it is one of:
* {@code Cache-Control}, {@code Content-Language}, {@code Expires},
* {@code Last-Modified}, or {@code Pragma}.
* <p>By default this is not set.
*/
public void setExposedHeaders(@Nullable List<String> exposedHeaders) {
@ -411,9 +426,7 @@ public class CorsConfiguration {
}
/**
* Add a response header to expose.
* <p>The special value {@code "*"} allows all headers to be exposed for
* non-credentialed requests.
* Variant of {@link #setExposedHeaders} for adding one exposed header at a time.
*/
public void addExposedHeader(String exposedHeader) {
if (this.exposedHeaders == null) {
@ -424,6 +437,15 @@ public class CorsConfiguration {
/**
* Whether user credentials are supported.
* <p>Setting this property has an impact on how {@link #setAllowedOrigins(List)
* origins}, {@link #setAllowedOriginPatterns(List) originPatterns},
* {@link #setAllowedMethods(List) allowedMethods} and
* {@link #setAllowedHeaders(List) allowedHeaders} are processed, see related
* API documentation for more details.
* <p><strong>NOTE:</strong> Be aware that this option establishes a high
* level of trust with the configured domains and also increases the surface
* attack of the web application by exposing sensitive user-specific
* information such as cookies and CSRF tokens.
* <p>By default this is not set (i.e. user credentials are not supported).
*/
public void setAllowCredentials(@Nullable Boolean allowCredentials) {

View File

@ -191,7 +191,7 @@ public class DefaultCorsProcessor implements CorsProcessor {
/**
* Check the headers and determine the headers for the response of a
* pre-flight request. The default implementation simply delegates to
* {@link org.springframework.web.cors.CorsConfiguration#checkOrigin(String)}.
* {@link org.springframework.web.cors.CorsConfiguration#checkHeaders(List)}.
*/
@Nullable
protected List<String> checkHeaders(CorsConfiguration config, List<String> requestHeaders) {

View File

@ -188,7 +188,7 @@ public class DefaultCorsProcessor implements CorsProcessor {
/**
* Check the headers and determine the headers for the response of a
* pre-flight request. The default implementation simply delegates to
* {@link CorsConfiguration#checkOrigin(String)}.
* {@link CorsConfiguration#checkHeaders(List)}.
*/
@Nullable
protected List<String> checkHeaders(CorsConfiguration config, List<String> requestHeaders) {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2023 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.
@ -76,9 +76,11 @@ public class CorsRegistration {
/**
* Set the HTTP methods to allow, e.g. {@code "GET"}, {@code "POST"}, etc.
* <p>The special value {@code "*"} allows all methods.
* <p>By default "simple" methods {@code GET}, {@code HEAD}, and {@code POST}
* The special value {@code "*"} allows all methods. By default,
* "simple" methods {@code GET}, {@code HEAD}, and {@code POST}
* are allowed.
* <p>Please, see {@link CorsConfiguration#setAllowedMethods(List)} for
* details.
*/
public CorsRegistration allowedMethods(String... methods) {
this.config.setAllowedMethods(Arrays.asList(methods));
@ -87,11 +89,10 @@ public class CorsRegistration {
/**
* Set the list of headers that a pre-flight request can list as allowed
* for use during an actual request.
* <p>The special value {@code "*"} may be used to allow all headers.
* <p>A header name is not required to be listed if it is one of:
* {@code Cache-Control}, {@code Content-Language}, {@code Expires},
* {@code Last-Modified}, or {@code Pragma} as per the CORS spec.
* for use during an actual request. The special value {@code "*"}
* may be used to allow all headers.
* <p>Please, see {@link CorsConfiguration#setAllowedHeaders(List)} for
* details.
* <p>By default all headers are allowed.
*/
public CorsRegistration allowedHeaders(String... headers) {
@ -100,12 +101,11 @@ public class CorsRegistration {
}
/**
* Set the list of response headers other than "simple" headers, i.e.
* {@code Cache-Control}, {@code Content-Language}, {@code Content-Type},
* {@code Expires}, {@code Last-Modified}, or {@code Pragma}, that an
* actual response might have and can be exposed.
* <p>The special value {@code "*"} allows all headers to be exposed for
* non-credentialed requests.
* Set the list of response headers that an actual response might have and
* can be exposed. The special value {@code "*"} allows all headers to be
* exposed.
* <p>Please, see {@link CorsConfiguration#setExposedHeaders(List)} for
* details.
* <p>By default this is not set.
*/
public CorsRegistration exposedHeaders(String... headers) {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2023 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.
@ -77,9 +77,11 @@ public class CorsRegistration {
/**
* Set the HTTP methods to allow, e.g. {@code "GET"}, {@code "POST"}, etc.
* <p>The special value {@code "*"} allows all methods.
* <p>By default "simple" methods {@code GET}, {@code HEAD}, and {@code POST}
* The special value {@code "*"} allows all methods. By default,
* "simple" methods {@code GET}, {@code HEAD}, and {@code POST}
* are allowed.
* <p>Please, see {@link CorsConfiguration#setAllowedMethods(List)} for
* details.
*/
public CorsRegistration allowedMethods(String... methods) {
this.config.setAllowedMethods(Arrays.asList(methods));
@ -88,11 +90,10 @@ public class CorsRegistration {
/**
* Set the list of headers that a pre-flight request can list as allowed
* for use during an actual request.
* <p>The special value {@code "*"} may be used to allow all headers.
* <p>A header name is not required to be listed if it is one of:
* {@code Cache-Control}, {@code Content-Language}, {@code Expires},
* {@code Last-Modified}, or {@code Pragma} as per the CORS spec.
* for use during an actual request. The special value {@code "*"}
* may be used to allow all headers.
* <p>Please, see {@link CorsConfiguration#setAllowedHeaders(List)} for
* details.
* <p>By default all headers are allowed.
*/
public CorsRegistration allowedHeaders(String... headers) {
@ -101,12 +102,11 @@ public class CorsRegistration {
}
/**
* Set the list of response headers other than "simple" headers, i.e.
* {@code Cache-Control}, {@code Content-Language}, {@code Content-Type},
* {@code Expires}, {@code Last-Modified}, or {@code Pragma}, that an
* actual response might have and can be exposed.
* <p>The special value {@code "*"} allows all headers to be exposed for
* non-credentialed requests.
* Set the list of response headers that an actual response might have and
* can be exposed. The special value {@code "*"} allows all headers to be
* exposed.
* <p>Please, see {@link CorsConfiguration#setExposedHeaders(List)} for
* details.
* <p>By default this is not set.
*/
public CorsRegistration exposedHeaders(String... headers) {