Skip to content

Commit 76b8bb2

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 gh-31143
1 parent db76542 commit 76b8bb2

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

Lines changed: 9 additions & 18 deletions
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.
@@ -80,41 +80,32 @@
8080

8181
/**
8282
* The list of request headers that are permitted in actual requests,
83-
* possibly {@code "*"} to allow all headers.
84-
* <p>Allowed headers are listed in the {@code Access-Control-Allow-Headers}
85-
* response header of preflight requests.
86-
* <p>A header name is not required to be listed if it is one of:
87-
* {@code Cache-Control}, {@code Content-Language}, {@code Expires},
88-
* {@code Last-Modified}, or {@code Pragma} as per the CORS spec.
83+
* possibly {@code "*"} to allow all headers. Please, see
84+
* {@link CorsConfiguration#setAllowedHeaders(List)} for details.
8985
* <p>By default all requested headers are allowed.
9086
*/
9187
String[] allowedHeaders() default {};
9288

9389
/**
9490
* The List of response headers that the user-agent will allow the client
95-
* to access on an actual response, other than "simple" headers, i.e.
96-
* {@code Cache-Control}, {@code Content-Language}, {@code Content-Type},
97-
* {@code Expires}, {@code Last-Modified}, or {@code Pragma},
98-
* <p>Exposed headers are listed in the {@code Access-Control-Expose-Headers}
99-
* response header of actual CORS requests.
100-
* <p>The special value {@code "*"} allows all headers to be exposed for
101-
* non-credentialed requests.
91+
* to access on an actual response, possibly {@code "*"} to expose all headers.
92+
* Please, see {@link CorsConfiguration#setExposedHeaders(List)} for details.
10293
* <p>By default no headers are listed as exposed.
10394
*/
10495
String[] exposedHeaders() default {};
10596

10697
/**
107-
* The list of supported HTTP request methods.
98+
* The list of supported HTTP request methods. Please, see
99+
* {@link CorsConfiguration#setAllowedMethods(List)} for details.
108100
* <p>By default the supported methods are the same as the ones to which a
109101
* controller method is mapped.
110102
*/
111103
RequestMethod[] methods() default {};
112104

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

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

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -280,8 +280,12 @@ private static void parseCommaDelimitedOrigin(String rawValue, Consumer<String>
280280

281281
/**
282282
* Set the HTTP methods to allow, e.g. {@code "GET"}, {@code "POST"},
283-
* {@code "PUT"}, etc.
284-
* <p>The special value {@code "*"} allows all methods.
283+
* {@code "PUT"}, etc. The special value {@code "*"} allows all methods.
284+
* <p>{@code Access-Control-Allow-Methods} response header is set either
285+
* to the configured method or to {@code "*"}. Keep in mind however that the
286+
* CORS spec does not allow {@code "*"} when {@link #setAllowCredentials
287+
* allowCredentials} is set to {@code true}, that combination is handled
288+
* by copying the method specified in the CORS preflight request.
285289
* <p>If not set, only {@code "GET"} and {@code "HEAD"} are allowed.
286290
* <p>By default this is not set.
287291
* <p><strong>Note:</strong> CORS checks use values from "Forwarded"
@@ -312,24 +316,24 @@ public void setAllowedMethods(@Nullable List<String> allowedMethods) {
312316
/**
313317
* Return the allowed HTTP methods, or {@code null} in which case
314318
* only {@code "GET"} and {@code "HEAD"} allowed.
319+
* @see #setAllowedMethods(List)
315320
* @see #addAllowedMethod(HttpMethod)
316321
* @see #addAllowedMethod(String)
317-
* @see #setAllowedMethods(List)
318322
*/
319323
@Nullable
320324
public List<String> getAllowedMethods() {
321325
return this.allowedMethods;
322326
}
323327

324328
/**
325-
* Add an HTTP method to allow.
329+
* Variant of {@link #setAllowedMethods} for adding one allowed method at a time.
326330
*/
327331
public void addAllowedMethod(HttpMethod method) {
328332
addAllowedMethod(method.name());
329333
}
330334

331335
/**
332-
* Add an HTTP method to allow.
336+
* Variant of {@link #setAllowedMethods} for adding one allowed method at a time.
333337
*/
334338
public void addAllowedMethod(String method) {
335339
if (StringUtils.hasText(method)) {
@@ -352,9 +356,13 @@ else if (this.resolvedMethods != null) {
352356

353357
/**
354358
* Set the list of headers that a pre-flight request can list as allowed
355-
* for use during an actual request.
356-
* <p>The special value {@code "*"} allows actual requests to send any
357-
* header.
359+
* for use during an actual request. The special value {@code "*"} allows
360+
* actual requests to send any header.
361+
* <p>{@code Access-Control-Allow-Headers} response header is set either
362+
* to the configured list of headers or to {@code "*"}. Keep in mind however
363+
* that the CORS spec does not allow {@code "*"} when {@link #setAllowCredentials
364+
* allowCredentials} is set to {@code true}, that combination is handled by
365+
* copying the headers specified in the CORS preflight request.
358366
* <p>A header name is not required to be listed if it is one of:
359367
* {@code Cache-Control}, {@code Content-Language}, {@code Expires},
360368
* {@code Last-Modified}, or {@code Pragma}.
@@ -375,7 +383,7 @@ public List<String> getAllowedHeaders() {
375383
}
376384

377385
/**
378-
* Add an actual request header to allow.
386+
* Variant of {@link #setAllowedHeaders(List)} for adding one allowed header at a time.
379387
*/
380388
public void addAllowedHeader(String allowedHeader) {
381389
if (this.allowedHeaders == null) {
@@ -388,12 +396,19 @@ else if (this.allowedHeaders == DEFAULT_PERMIT_ALL) {
388396
}
389397

390398
/**
391-
* Set the list of response headers other than simple headers (i.e.
392-
* {@code Cache-Control}, {@code Content-Language}, {@code Content-Type},
393-
* {@code Expires}, {@code Last-Modified}, or {@code Pragma}) that an
394-
* actual response might have and can be exposed.
395-
* <p>The special value {@code "*"} allows all headers to be exposed for
396-
* non-credentialed requests.
399+
* Set the list of response headers that an actual response might have
400+
* and can be exposed to the client. The special value {@code "*"}
401+
* allows all headers to be exposed.
402+
* <p>{@code Access-Control-Expose-Headers} response header is set either
403+
* to the configured list of headers or to {@code "*"}. While the CORS
404+
* spec does not allow {@code "*"} when {@code Access-Control-Allow-Credentials}
405+
* is set to {@code true}, most browsers support it and
406+
* the response headers are not all available during the CORS processing,
407+
* so as a consequence {@code "*"} is the header value used when specified
408+
* regardless of the value of the `allowCredentials` property.
409+
* <p>A header name is not required to be listed if it is one of:
410+
* {@code Cache-Control}, {@code Content-Language}, {@code Expires},
411+
* {@code Last-Modified}, or {@code Pragma}.
397412
* <p>By default this is not set.
398413
*/
399414
public void setExposedHeaders(@Nullable List<String> exposedHeaders) {
@@ -411,9 +426,7 @@ public List<String> getExposedHeaders() {
411426
}
412427

413428
/**
414-
* Add a response header to expose.
415-
* <p>The special value {@code "*"} allows all headers to be exposed for
416-
* non-credentialed requests.
429+
* Variant of {@link #setExposedHeaders} for adding one exposed header at a time.
417430
*/
418431
public void addExposedHeader(String exposedHeader) {
419432
if (this.exposedHeaders == null) {
@@ -424,6 +437,15 @@ public void addExposedHeader(String exposedHeader) {
424437

425438
/**
426439
* Whether user credentials are supported.
440+
* <p>Setting this property has an impact on how {@link #setAllowedOrigins(List)
441+
* origins}, {@link #setAllowedOriginPatterns(List) originPatterns},
442+
* {@link #setAllowedMethods(List) allowedMethods} and
443+
* {@link #setAllowedHeaders(List) allowedHeaders} are processed, see related
444+
* API documentation for more details.
445+
* <p><strong>NOTE:</strong> Be aware that this option establishes a high
446+
* level of trust with the configured domains and also increases the surface
447+
* attack of the web application by exposing sensitive user-specific
448+
* information such as cookies and CSRF tokens.
427449
* <p>By default this is not set (i.e. user credentials are not supported).
428450
*/
429451
public void setAllowCredentials(@Nullable Boolean allowCredentials) {

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

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

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ private HttpMethod getMethodToUse(ServerHttpRequest request, boolean isPreFlight
188188
/**
189189
* Check the headers and determine the headers for the response of a
190190
* pre-flight request. The default implementation simply delegates to
191-
* {@link CorsConfiguration#checkOrigin(String)}.
191+
* {@link CorsConfiguration#checkHeaders(List)}.
192192
*/
193193
@Nullable
194194
protected List<String> checkHeaders(CorsConfiguration config, List<String> requestHeaders) {

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

Lines changed: 14 additions & 14 deletions
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

Lines changed: 14 additions & 14 deletions
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)