Skip to content

Commit 75faf69

Browse files
committed
Refine CORS documentation for wildcard processing
This commit refines CORS wildcard processing Javadoc to provides more details on how wildcards are handled for Access-Control-Allow-Methods, Access-Control-Allow-Headers and Access-Control-Expose-Headers CORS headers. For Access-Control-Expose-Headers, it is not possible to copy the response headers which are not available at the point when the CorsProcessor is invoked. Since all the major browsers seem to support wildcard including on requests with credentials, and since this is ultimately the user-agent responsibility to check on client-side what is authorized or not, Spring Framework continues to support this use case. See spring-projectsgh-31168
1 parent 39c225c commit 75faf69

File tree

6 files changed

+79
-66
lines changed

6 files changed

+79
-66
lines changed

spring-web/src/main/java/org/springframework/web/bind/annotation/CrossOrigin.java

+9-18
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2021 the original author or authors.
2+
* Copyright 2002-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -97,41 +97,32 @@
9797

9898
/**
9999
* The list of request headers that are permitted in actual requests,
100-
* possibly {@code "*"} to allow all headers.
101-
* <p>Allowed headers are listed in the {@code Access-Control-Allow-Headers}
102-
* response header of preflight requests.
103-
* <p>A header name is not required to be listed if it is one of:
104-
* {@code Cache-Control}, {@code Content-Language}, {@code Expires},
105-
* {@code Last-Modified}, or {@code Pragma} as per the CORS spec.
100+
* possibly {@code "*"} to allow all headers. Please, see
101+
* {@link CorsConfiguration#setAllowedHeaders(List)} for details.
106102
* <p>By default all requested headers are allowed.
107103
*/
108104
String[] allowedHeaders() default {};
109105

110106
/**
111107
* The List of response headers that the user-agent will allow the client
112-
* to access on an actual response, other than "simple" headers, i.e.
113-
* {@code Cache-Control}, {@code Content-Language}, {@code Content-Type},
114-
* {@code Expires}, {@code Last-Modified}, or {@code Pragma},
115-
* <p>Exposed headers are listed in the {@code Access-Control-Expose-Headers}
116-
* response header of actual CORS requests.
117-
* <p>The special value {@code "*"} allows all headers to be exposed for
118-
* non-credentialed requests.
108+
* to access on an actual response, possibly {@code "*"} to expose all headers.
109+
* Please, see {@link CorsConfiguration#setExposedHeaders(List)} for details.
119110
* <p>By default no headers are listed as exposed.
120111
*/
121112
String[] exposedHeaders() default {};
122113

123114
/**
124-
* The list of supported HTTP request methods.
115+
* The list of supported HTTP request methods. Please, see
116+
* {@link CorsConfiguration#setAllowedMethods(List)} for details.
125117
* <p>By default the supported methods are the same as the ones to which a
126118
* controller method is mapped.
127119
*/
128120
RequestMethod[] methods() default {};
129121

130122
/**
131123
* Whether the browser should send credentials, such as cookies along with
132-
* cross domain requests, to the annotated endpoint. The configured value is
133-
* set on the {@code Access-Control-Allow-Credentials} response header of
134-
* preflight requests.
124+
* cross domain requests, to the annotated endpoint. Please, see
125+
* {@link CorsConfiguration#setAllowCredentials(Boolean)} for details.
135126
* <p><strong>NOTE:</strong> Be aware that this option establishes a high
136127
* level of trust with the configured domains and also increases the surface
137128
* attack of the web application by exposing sensitive user-specific

spring-web/src/main/java/org/springframework/web/cors/CorsConfiguration.java

+40-18
Original file line numberDiff line numberDiff line change
@@ -237,8 +237,12 @@ public void addAllowedOriginPattern(@Nullable String originPattern) {
237237

238238
/**
239239
* Set the HTTP methods to allow, e.g. {@code "GET"}, {@code "POST"},
240-
* {@code "PUT"}, etc.
241-
* <p>The special value {@code "*"} allows all methods.
240+
* {@code "PUT"}, etc. The special value {@code "*"} allows all methods.
241+
* <p>{@code Access-Control-Allow-Methods} response header is set either
242+
* to the configured method or to {@code "*"}. Keep in mind however that the
243+
* CORS spec does not allow {@code "*"} when {@link #setAllowCredentials
244+
* allowCredentials} is set to {@code true}, that combination is handled
245+
* by copying the method specified in the CORS preflight request.
242246
* <p>If not set, only {@code "GET"} and {@code "HEAD"} are allowed.
243247
* <p>By default this is not set.
244248
* <p><strong>Note:</strong> CORS checks use values from "Forwarded"
@@ -269,24 +273,24 @@ public void setAllowedMethods(@Nullable List<String> allowedMethods) {
269273
/**
270274
* Return the allowed HTTP methods, or {@code null} in which case
271275
* only {@code "GET"} and {@code "HEAD"} allowed.
276+
* @see #setAllowedMethods(List)
272277
* @see #addAllowedMethod(HttpMethod)
273278
* @see #addAllowedMethod(String)
274-
* @see #setAllowedMethods(List)
275279
*/
276280
@Nullable
277281
public List<String> getAllowedMethods() {
278282
return this.allowedMethods;
279283
}
280284

281285
/**
282-
* Add an HTTP method to allow.
286+
* Variant of {@link #setAllowedMethods} for adding one allowed method at a time.
283287
*/
284288
public void addAllowedMethod(HttpMethod method) {
285289
addAllowedMethod(method.name());
286290
}
287291

288292
/**
289-
* Add an HTTP method to allow.
293+
* Variant of {@link #setAllowedMethods} for adding one allowed method at a time.
290294
*/
291295
public void addAllowedMethod(String method) {
292296
if (StringUtils.hasText(method)) {
@@ -309,9 +313,13 @@ else if (this.resolvedMethods != null) {
309313

310314
/**
311315
* Set the list of headers that a pre-flight request can list as allowed
312-
* for use during an actual request.
313-
* <p>The special value {@code "*"} allows actual requests to send any
314-
* header.
316+
* for use during an actual request. The special value {@code "*"} allows
317+
* actual requests to send any header.
318+
* <p>{@code Access-Control-Allow-Headers} response header is set either
319+
* to the configured list of headers or to {@code "*"}. Keep in mind however
320+
* that the CORS spec does not allow {@code "*"} when {@link #setAllowCredentials
321+
* allowCredentials} is set to {@code true}, that combination is handled by
322+
* copying the headers specified in the CORS preflight request.
315323
* <p>A header name is not required to be listed if it is one of:
316324
* {@code Cache-Control}, {@code Content-Language}, {@code Expires},
317325
* {@code Last-Modified}, or {@code Pragma}.
@@ -332,7 +340,7 @@ public List<String> getAllowedHeaders() {
332340
}
333341

334342
/**
335-
* Add an actual request header to allow.
343+
* Variant of {@link #setAllowedHeaders(List)} for adding one allowed header at a time.
336344
*/
337345
public void addAllowedHeader(String allowedHeader) {
338346
if (this.allowedHeaders == null) {
@@ -345,12 +353,19 @@ else if (this.allowedHeaders == DEFAULT_PERMIT_ALL) {
345353
}
346354

347355
/**
348-
* Set the list of response headers other than simple headers (i.e.
349-
* {@code Cache-Control}, {@code Content-Language}, {@code Content-Type},
350-
* {@code Expires}, {@code Last-Modified}, or {@code Pragma}) that an
351-
* actual response might have and can be exposed.
352-
* <p>The special value {@code "*"} allows all headers to be exposed for
353-
* non-credentialed requests.
356+
* Set the list of response headers that an actual response might have
357+
* and can be exposed to the client. The special value {@code "*"}
358+
* allows all headers to be exposed.
359+
* <p>{@code Access-Control-Expose-Headers} response header is set either
360+
* to the configured list of headers or to {@code "*"}. While the CORS
361+
* spec does not allow {@code "*"} when {@code Access-Control-Allow-Credentials}
362+
* is set to {@code true}, most browsers support it and
363+
* the response headers are not all available during the CORS processing,
364+
* so as a consequence {@code "*"} is the header value used when specified
365+
* regardless of the value of the `allowCredentials` property.
366+
* <p>A header name is not required to be listed if it is one of:
367+
* {@code Cache-Control}, {@code Content-Language}, {@code Expires},
368+
* {@code Last-Modified}, or {@code Pragma}.
354369
* <p>By default this is not set.
355370
*/
356371
public void setExposedHeaders(@Nullable List<String> exposedHeaders) {
@@ -368,9 +383,7 @@ public List<String> getExposedHeaders() {
368383
}
369384

370385
/**
371-
* Add a response header to expose.
372-
* <p>The special value {@code "*"} allows all headers to be exposed for
373-
* non-credentialed requests.
386+
* Variant of {@link #setExposedHeaders} for adding one exposed header at a time.
374387
*/
375388
public void addExposedHeader(String exposedHeader) {
376389
if (this.exposedHeaders == null) {
@@ -381,6 +394,15 @@ public void addExposedHeader(String exposedHeader) {
381394

382395
/**
383396
* Whether user credentials are supported.
397+
* <p>Setting this property has an impact on how {@link #setAllowedOrigins(List)
398+
* origins}, {@link #setAllowedOriginPatterns(List) originPatterns},
399+
* {@link #setAllowedMethods(List) allowedMethods} and
400+
* {@link #setAllowedHeaders(List) allowedHeaders} are processed, see related
401+
* API documentation for more details.
402+
* <p><strong>NOTE:</strong> Be aware that this option establishes a high
403+
* level of trust with the configured domains and also increases the surface
404+
* attack of the web application by exposing sensitive user-specific
405+
* information such as cookies and CSRF tokens.
384406
* <p>By default this is not set (i.e. user credentials are not supported).
385407
*/
386408
public void setAllowCredentials(@Nullable Boolean allowCredentials) {

spring-web/src/main/java/org/springframework/web/cors/DefaultCorsProcessor.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ private HttpMethod getMethodToUse(ServerHttpRequest request, boolean isPreFlight
192192
/**
193193
* Check the headers and determine the headers for the response of a
194194
* pre-flight request. The default implementation simply delegates to
195-
* {@link org.springframework.web.cors.CorsConfiguration#checkOrigin(String)}.
195+
* {@link org.springframework.web.cors.CorsConfiguration#checkHeaders(List)}.
196196
*/
197197
@Nullable
198198
protected List<String> checkHeaders(CorsConfiguration config, List<String> requestHeaders) {

spring-web/src/main/java/org/springframework/web/cors/reactive/DefaultCorsProcessor.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ private HttpMethod getMethodToUse(ServerHttpRequest request, boolean isPreFlight
190190
/**
191191
* Check the headers and determine the headers for the response of a
192192
* pre-flight request. The default implementation simply delegates to
193-
* {@link CorsConfiguration#checkOrigin(String)}.
193+
* {@link CorsConfiguration#checkHeaders(List)}.
194194
*/
195195
@Nullable
196196

spring-webflux/src/main/java/org/springframework/web/reactive/config/CorsRegistration.java

+14-14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2021 the original author or authors.
2+
* Copyright 2002-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -76,9 +76,11 @@ public CorsRegistration allowedOriginPatterns(String... patterns) {
7676

7777
/**
7878
* Set the HTTP methods to allow, e.g. {@code "GET"}, {@code "POST"}, etc.
79-
* <p>The special value {@code "*"} allows all methods.
80-
* <p>By default "simple" methods {@code GET}, {@code HEAD}, and {@code POST}
79+
* The special value {@code "*"} allows all methods. By default,
80+
* "simple" methods {@code GET}, {@code HEAD}, and {@code POST}
8181
* are allowed.
82+
* <p>Please, see {@link CorsConfiguration#setAllowedMethods(List)} for
83+
* details.
8284
*/
8385
public CorsRegistration allowedMethods(String... methods) {
8486
this.config.setAllowedMethods(Arrays.asList(methods));
@@ -87,11 +89,10 @@ public CorsRegistration allowedMethods(String... methods) {
8789

8890
/**
8991
* Set the list of headers that a pre-flight request can list as allowed
90-
* for use during an actual request.
91-
* <p>The special value {@code "*"} may be used to allow all headers.
92-
* <p>A header name is not required to be listed if it is one of:
93-
* {@code Cache-Control}, {@code Content-Language}, {@code Expires},
94-
* {@code Last-Modified}, or {@code Pragma} as per the CORS spec.
92+
* for use during an actual request. The special value {@code "*"}
93+
* may be used to allow all headers.
94+
* <p>Please, see {@link CorsConfiguration#setAllowedHeaders(List)} for
95+
* details.
9596
* <p>By default all headers are allowed.
9697
*/
9798
public CorsRegistration allowedHeaders(String... headers) {
@@ -100,12 +101,11 @@ public CorsRegistration allowedHeaders(String... headers) {
100101
}
101102

102103
/**
103-
* Set the list of response headers other than "simple" headers, i.e.
104-
* {@code Cache-Control}, {@code Content-Language}, {@code Content-Type},
105-
* {@code Expires}, {@code Last-Modified}, or {@code Pragma}, that an
106-
* actual response might have and can be exposed.
107-
* <p>The special value {@code "*"} allows all headers to be exposed for
108-
* non-credentialed requests.
104+
* Set the list of response headers that an actual response might have and
105+
* can be exposed. The special value {@code "*"} allows all headers to be
106+
* exposed.
107+
* <p>Please, see {@link CorsConfiguration#setExposedHeaders(List)} for
108+
* details.
109109
* <p>By default this is not set.
110110
*/
111111
public CorsRegistration exposedHeaders(String... headers) {

spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/CorsRegistration.java

+14-14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2021 the original author or authors.
2+
* Copyright 2002-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -77,9 +77,11 @@ public CorsRegistration allowedOriginPatterns(String... patterns) {
7777

7878
/**
7979
* Set the HTTP methods to allow, e.g. {@code "GET"}, {@code "POST"}, etc.
80-
* <p>The special value {@code "*"} allows all methods.
81-
* <p>By default "simple" methods {@code GET}, {@code HEAD}, and {@code POST}
80+
* The special value {@code "*"} allows all methods. By default,
81+
* "simple" methods {@code GET}, {@code HEAD}, and {@code POST}
8282
* are allowed.
83+
* <p>Please, see {@link CorsConfiguration#setAllowedMethods(List)} for
84+
* details.
8385
*/
8486
public CorsRegistration allowedMethods(String... methods) {
8587
this.config.setAllowedMethods(Arrays.asList(methods));
@@ -88,11 +90,10 @@ public CorsRegistration allowedMethods(String... methods) {
8890

8991
/**
9092
* Set the list of headers that a pre-flight request can list as allowed
91-
* for use during an actual request.
92-
* <p>The special value {@code "*"} may be used to allow all headers.
93-
* <p>A header name is not required to be listed if it is one of:
94-
* {@code Cache-Control}, {@code Content-Language}, {@code Expires},
95-
* {@code Last-Modified}, or {@code Pragma} as per the CORS spec.
93+
* for use during an actual request. The special value {@code "*"}
94+
* may be used to allow all headers.
95+
* <p>Please, see {@link CorsConfiguration#setAllowedHeaders(List)} for
96+
* details.
9697
* <p>By default all headers are allowed.
9798
*/
9899
public CorsRegistration allowedHeaders(String... headers) {
@@ -101,12 +102,11 @@ public CorsRegistration allowedHeaders(String... headers) {
101102
}
102103

103104
/**
104-
* Set the list of response headers other than "simple" headers, i.e.
105-
* {@code Cache-Control}, {@code Content-Language}, {@code Content-Type},
106-
* {@code Expires}, {@code Last-Modified}, or {@code Pragma}, that an
107-
* actual response might have and can be exposed.
108-
* <p>The special value {@code "*"} allows all headers to be exposed for
109-
* non-credentialed requests.
105+
* Set the list of response headers that an actual response might have and
106+
* can be exposed. The special value {@code "*"} allows all headers to be
107+
* exposed.
108+
* <p>Please, see {@link CorsConfiguration#setExposedHeaders(List)} for
109+
* details.
110110
* <p>By default this is not set.
111111
*/
112112
public CorsRegistration exposedHeaders(String... headers) {

0 commit comments

Comments
 (0)