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 0a568d25db2b..68fbee19e9b9 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-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. @@ -97,31 +97,23 @@ /** * The list of request headers that are permitted in actual requests, - * possibly {@code "*"} to allow all headers. - *

Allowed headers are listed in the {@code Access-Control-Allow-Headers} - * response header of preflight requests. - *

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. *

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}, - *

Exposed headers are listed in the {@code Access-Control-Expose-Headers} - * response header of actual CORS requests. - *

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. *

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. *

By default the supported methods are the same as the ones to which a * controller method is mapped. */ @@ -129,9 +121,8 @@ /** * 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. *

NOTE: 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 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 f88db838bbb9..f36edf31e0ec 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 @@ -237,8 +237,12 @@ public void addAllowedOriginPattern(@Nullable String originPattern) { /** * Set the HTTP methods to allow, e.g. {@code "GET"}, {@code "POST"}, - * {@code "PUT"}, etc. - *

The special value {@code "*"} allows all methods. + * {@code "PUT"}, etc. The special value {@code "*"} allows all methods. + *

{@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. *

If not set, only {@code "GET"} and {@code "HEAD"} are allowed. *

By default this is not set. *

Note: CORS checks use values from "Forwarded" @@ -269,9 +273,9 @@ public void setAllowedMethods(@Nullable List allowedMethods) { /** * 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 getAllowedMethods() { @@ -279,14 +283,14 @@ public List getAllowedMethods() { } /** - * 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)) { @@ -309,9 +313,13 @@ else if (this.resolvedMethods != null) { /** * Set the list of headers that a pre-flight request can list as allowed - * for use during an actual request. - *

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. + *

{@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. *

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}. @@ -332,7 +340,7 @@ public List getAllowedHeaders() { } /** - * 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) { @@ -345,12 +353,19 @@ else if (this.allowedHeaders == DEFAULT_PERMIT_ALL) { } /** - * 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. - *

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. + *

{@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. + *

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}. *

By default this is not set. */ public void setExposedHeaders(@Nullable List exposedHeaders) { @@ -368,9 +383,7 @@ public List getExposedHeaders() { } /** - * Add a response header to expose. - *

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) { @@ -381,6 +394,15 @@ public void addExposedHeader(String exposedHeader) { /** * Whether user credentials are supported. + *

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. + *

NOTE: 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. *

By default this is not set (i.e. user credentials are not supported). */ public void setAllowCredentials(@Nullable Boolean allowCredentials) { diff --git a/spring-web/src/main/java/org/springframework/web/cors/DefaultCorsProcessor.java b/spring-web/src/main/java/org/springframework/web/cors/DefaultCorsProcessor.java index 37d3fb8c9dd9..fcff9e4be4ea 100644 --- a/spring-web/src/main/java/org/springframework/web/cors/DefaultCorsProcessor.java +++ b/spring-web/src/main/java/org/springframework/web/cors/DefaultCorsProcessor.java @@ -192,7 +192,7 @@ private HttpMethod getMethodToUse(ServerHttpRequest request, boolean isPreFlight /** * 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 checkHeaders(CorsConfiguration config, List requestHeaders) { diff --git a/spring-web/src/main/java/org/springframework/web/cors/reactive/DefaultCorsProcessor.java b/spring-web/src/main/java/org/springframework/web/cors/reactive/DefaultCorsProcessor.java index 70796c384808..d1e34dcbfb84 100644 --- a/spring-web/src/main/java/org/springframework/web/cors/reactive/DefaultCorsProcessor.java +++ b/spring-web/src/main/java/org/springframework/web/cors/reactive/DefaultCorsProcessor.java @@ -190,7 +190,7 @@ private HttpMethod getMethodToUse(ServerHttpRequest request, boolean isPreFlight /** * 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 diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/config/CorsRegistration.java b/spring-webflux/src/main/java/org/springframework/web/reactive/config/CorsRegistration.java index 327c83ff8177..383505c4c7fa 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/config/CorsRegistration.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/config/CorsRegistration.java @@ -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 CorsRegistration allowedOriginPatterns(String... patterns) { /** * Set the HTTP methods to allow, e.g. {@code "GET"}, {@code "POST"}, etc. - *

The special value {@code "*"} allows all methods. - *

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. + *

Please, see {@link CorsConfiguration#setAllowedMethods(List)} for + * details. */ public CorsRegistration allowedMethods(String... methods) { this.config.setAllowedMethods(Arrays.asList(methods)); @@ -87,11 +89,10 @@ public CorsRegistration allowedMethods(String... methods) { /** * Set the list of headers that a pre-flight request can list as allowed - * for use during an actual request. - *

The special value {@code "*"} may be used to allow all headers. - *

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. + *

Please, see {@link CorsConfiguration#setAllowedHeaders(List)} for + * details. *

By default all headers are allowed. */ public CorsRegistration allowedHeaders(String... headers) { @@ -100,12 +101,11 @@ public CorsRegistration allowedHeaders(String... headers) { } /** - * 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. - *

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. + *

Please, see {@link CorsConfiguration#setExposedHeaders(List)} for + * details. *

By default this is not set. */ public CorsRegistration exposedHeaders(String... headers) { diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/CorsRegistration.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/CorsRegistration.java index 523f5dcc0c5c..e1a25396c7cf 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/CorsRegistration.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/CorsRegistration.java @@ -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 CorsRegistration allowedOriginPatterns(String... patterns) { /** * Set the HTTP methods to allow, e.g. {@code "GET"}, {@code "POST"}, etc. - *

The special value {@code "*"} allows all methods. - *

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. + *

Please, see {@link CorsConfiguration#setAllowedMethods(List)} for + * details. */ public CorsRegistration allowedMethods(String... methods) { this.config.setAllowedMethods(Arrays.asList(methods)); @@ -88,11 +90,10 @@ public CorsRegistration allowedMethods(String... methods) { /** * Set the list of headers that a pre-flight request can list as allowed - * for use during an actual request. - *

The special value {@code "*"} may be used to allow all headers. - *

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. + *

Please, see {@link CorsConfiguration#setAllowedHeaders(List)} for + * details. *

By default all headers are allowed. */ public CorsRegistration allowedHeaders(String... headers) { @@ -101,12 +102,11 @@ public CorsRegistration allowedHeaders(String... headers) { } /** - * 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. - *

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. + *

Please, see {@link CorsConfiguration#setExposedHeaders(List)} for + * details. *

By default this is not set. */ public CorsRegistration exposedHeaders(String... headers) {