Disable CORS credentials by default
Access-Control-Allow-Credentials CORS header, used to allow cookies with CORS requests, is not set to true anymore by default when enabling CORS with @CrossOrigin or global CORS configuration in order to provide a more secured default CORS configuration. The related allowCredentials property now requires to be set to true explicitly in order to support cookies with CORS requests. Issue: SPR-16130
This commit is contained in:
parent
93f17dae47
commit
652e5c5584
|
@ -28,7 +28,7 @@ import org.springframework.web.cors.CorsConfiguration;
|
|||
/**
|
||||
* Marks the annotated method or type as permitting cross origin requests.
|
||||
*
|
||||
* <p>By default all origins and headers are permitted, credentials are allowed,
|
||||
* <p>By default all origins and headers are permitted, credentials are not allowed,
|
||||
* and the maximum age is set to 1800 seconds (30 minutes). The list of HTTP
|
||||
* methods is set to the methods on the {@code @RequestMapping} if not
|
||||
* explicitly set on {@code @CrossOrigin}.
|
||||
|
@ -64,7 +64,7 @@ public @interface CrossOrigin {
|
|||
* @deprecated as of Spring 5.0, in favor of using {@link CorsConfiguration#applyPermitDefaultValues}
|
||||
*/
|
||||
@Deprecated
|
||||
boolean DEFAULT_ALLOW_CREDENTIALS = true;
|
||||
boolean DEFAULT_ALLOW_CREDENTIALS = false;
|
||||
|
||||
/**
|
||||
* @deprecated as of Spring 5.0, in favor of using {@link CorsConfiguration#applyPermitDefaultValues}
|
||||
|
@ -118,12 +118,13 @@ public @interface CrossOrigin {
|
|||
|
||||
/**
|
||||
* Whether the browser should include any cookies associated with the
|
||||
* domain of the request being annotated.
|
||||
* <p>Set to {@code "false"} if such cookies should not included.
|
||||
* An empty string ({@code ""}) means <em>undefined</em>.
|
||||
* {@code "true"} means that the pre-flight response will include the header
|
||||
* {@code Access-Control-Allow-Credentials=true}.
|
||||
* <p>If undefined, credentials are allowed.
|
||||
* domain of the request being annotated. Be aware that enabling this option could
|
||||
* increase the surface attack of the web application (for example via exposing
|
||||
* sensitive user-specific information like CSRF tokens).
|
||||
* <p>Set to {@code "true"} means that the pre-flight response will include the header
|
||||
* {@code Access-Control-Allow-Credentials=true} so such cookies should be included.
|
||||
* <p>If undefined or set to {@code "false"}, such header is not included and
|
||||
* credentials are not allowed.
|
||||
*/
|
||||
String allowCredentials() default "";
|
||||
|
||||
|
|
|
@ -324,7 +324,6 @@ public class CorsConfiguration {
|
|||
* <li>Allow all origins, i.e. {@code "*"}.</li>
|
||||
* <li>Allow "simple" methods {@code GET}, {@code HEAD} and {@code POST}.</li>
|
||||
* <li>Allow all headers.</li>
|
||||
* <li>Allow credentials.</li>
|
||||
* <li>Set max age to 1800 seconds (30 minutes).</li>
|
||||
* </ul>
|
||||
*/
|
||||
|
@ -339,9 +338,6 @@ public class CorsConfiguration {
|
|||
if (this.allowedHeaders == null) {
|
||||
this.addAllowedHeader(ALL);
|
||||
}
|
||||
if (this.allowCredentials == null) {
|
||||
this.setAllowCredentials(true);
|
||||
}
|
||||
if (this.maxAge == null) {
|
||||
this.setMaxAge(1800L);
|
||||
}
|
||||
|
|
|
@ -113,9 +113,10 @@ public class CorsRegistration {
|
|||
}
|
||||
|
||||
/**
|
||||
* Whether user credentials are supported.
|
||||
* <p>By default this is set to {@code true} in which case user credentials
|
||||
* are supported.
|
||||
* Whether user credentials are supported. Be aware that enabling this option
|
||||
* could increase the surface attack of the web application (for example via
|
||||
* exposing sensitive user-specific information like CSRF tokens).
|
||||
* <p>By default credentials are not allowed.
|
||||
*/
|
||||
public CorsRegistration allowCredentials(boolean allowCredentials) {
|
||||
this.config.setAllowCredentials(allowCredentials);
|
||||
|
|
|
@ -104,8 +104,8 @@ public class CrossOriginAnnotationIntegrationTests extends AbstractRequestMappin
|
|||
public void actualRequestWithDefaultAnnotation() throws Exception {
|
||||
ResponseEntity<String> entity = performGet("/default", this.headers, String.class);
|
||||
assertEquals(HttpStatus.OK, entity.getStatusCode());
|
||||
assertEquals("http://site1.com", entity.getHeaders().getAccessControlAllowOrigin());
|
||||
assertEquals(true, entity.getHeaders().getAccessControlAllowCredentials());
|
||||
assertEquals("*", entity.getHeaders().getAccessControlAllowOrigin());
|
||||
assertEquals(false, entity.getHeaders().getAccessControlAllowCredentials());
|
||||
assertEquals("default", entity.getBody());
|
||||
}
|
||||
|
||||
|
@ -114,9 +114,9 @@ public class CrossOriginAnnotationIntegrationTests extends AbstractRequestMappin
|
|||
this.headers.add(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
|
||||
ResponseEntity<Void> entity = performOptions("/default", this.headers, Void.class);
|
||||
assertEquals(HttpStatus.OK, entity.getStatusCode());
|
||||
assertEquals("http://site1.com", entity.getHeaders().getAccessControlAllowOrigin());
|
||||
assertEquals("*", entity.getHeaders().getAccessControlAllowOrigin());
|
||||
assertEquals(1800, entity.getHeaders().getAccessControlMaxAge());
|
||||
assertEquals(true, entity.getHeaders().getAccessControlAllowCredentials());
|
||||
assertEquals(false, entity.getHeaders().getAccessControlAllowCredentials());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -78,7 +78,7 @@ public class GlobalCorsConfigIntegrationTests extends AbstractRequestMappingInte
|
|||
public void actualRequestWithCorsEnabled() throws Exception {
|
||||
ResponseEntity<String> entity = performGet("/cors", this.headers, String.class);
|
||||
assertEquals(HttpStatus.OK, entity.getStatusCode());
|
||||
assertEquals("http://localhost:9000", entity.getHeaders().getAccessControlAllowOrigin());
|
||||
assertEquals("*", entity.getHeaders().getAccessControlAllowOrigin());
|
||||
assertEquals("cors", entity.getBody());
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,7 @@ public class GlobalCorsConfigIntegrationTests extends AbstractRequestMappingInte
|
|||
this.headers.add(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
|
||||
ResponseEntity<String> entity = performOptions("/cors", this.headers, String.class);
|
||||
assertEquals(HttpStatus.OK, entity.getStatusCode());
|
||||
assertEquals("http://localhost:9000", entity.getHeaders().getAccessControlAllowOrigin());
|
||||
assertEquals("*", entity.getHeaders().getAccessControlAllowOrigin());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -115,9 +115,10 @@ public class CorsRegistration {
|
|||
}
|
||||
|
||||
/**
|
||||
* Whether user credentials are supported.
|
||||
* <p>By default this is set to {@code true} in which case user credentials
|
||||
* are supported.
|
||||
* Whether user credentials are supported. Be aware that enabling this option
|
||||
* could increase the surface attack of the web application (for example via
|
||||
* exposing sensitive user-specific information like CSRF tokens).
|
||||
* <p>By default credentials are not allowed.
|
||||
*/
|
||||
public CorsRegistration allowCredentials(boolean allowCredentials) {
|
||||
this.config.setAllowCredentials(allowCredentials);
|
||||
|
|
|
@ -903,7 +903,7 @@ public class MvcNamespaceTests {
|
|||
assertArrayEquals(new String[]{"GET", "HEAD", "POST"}, config.getAllowedMethods().toArray());
|
||||
assertArrayEquals(new String[]{"*"}, config.getAllowedHeaders().toArray());
|
||||
assertNull(config.getExposedHeaders());
|
||||
assertTrue(config.getAllowCredentials());
|
||||
assertNull(config.getAllowCredentials());
|
||||
assertEquals(Long.valueOf(1800), config.getMaxAge());
|
||||
}
|
||||
}
|
||||
|
@ -933,7 +933,7 @@ public class MvcNamespaceTests {
|
|||
assertArrayEquals(new String[]{"GET", "HEAD", "POST"}, config.getAllowedMethods().toArray());
|
||||
assertArrayEquals(new String[]{"*"}, config.getAllowedHeaders().toArray());
|
||||
assertNull(config.getExposedHeaders());
|
||||
assertTrue(config.getAllowCredentials());
|
||||
assertNull(config.getAllowCredentials());
|
||||
assertEquals(Long.valueOf(1800), config.getMaxAge());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -126,7 +126,7 @@ public class CrossOriginTests {
|
|||
assertNotNull(config);
|
||||
assertArrayEquals(new String[] {"GET"}, config.getAllowedMethods().toArray());
|
||||
assertArrayEquals(new String[] {"*"}, config.getAllowedOrigins().toArray());
|
||||
assertTrue(config.getAllowCredentials());
|
||||
assertNull(config.getAllowCredentials());
|
||||
assertArrayEquals(new String[] {"*"}, config.getAllowedHeaders().toArray());
|
||||
assertTrue(CollectionUtils.isEmpty(config.getExposedHeaders()));
|
||||
assertEquals(new Long(1800), config.getMaxAge());
|
||||
|
@ -155,7 +155,7 @@ public class CrossOriginTests {
|
|||
CorsConfiguration config = getCorsConfiguration(chain, false);
|
||||
assertNotNull(config);
|
||||
assertEquals(Arrays.asList("http://example.com"), config.getAllowedOrigins());
|
||||
assertTrue(config.getAllowCredentials());
|
||||
assertNull(config.getAllowCredentials());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -166,7 +166,7 @@ public class CrossOriginTests {
|
|||
CorsConfiguration config = getCorsConfiguration(chain, false);
|
||||
assertNotNull(config);
|
||||
assertEquals(Arrays.asList("http://example.com"), config.getAllowedOrigins());
|
||||
assertTrue(config.getAllowCredentials());
|
||||
assertNull(config.getAllowCredentials());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -243,7 +243,7 @@ public class CrossOriginTests {
|
|||
assertNotNull(config);
|
||||
assertArrayEquals(new String[] {"GET"}, config.getAllowedMethods().toArray());
|
||||
assertArrayEquals(new String[] {"*"}, config.getAllowedOrigins().toArray());
|
||||
assertTrue(config.getAllowCredentials());
|
||||
assertNull(config.getAllowCredentials());
|
||||
assertArrayEquals(new String[] {"*"}, config.getAllowedHeaders().toArray());
|
||||
assertTrue(CollectionUtils.isEmpty(config.getExposedHeaders()));
|
||||
assertEquals(new Long(1800), config.getMaxAge());
|
||||
|
|
|
@ -24,6 +24,13 @@ implementation (https://github.com/spring-projects/spring-framework/blob/master/
|
|||
by default) in order to add the relevant CORS response headers (like `Access-Control-Allow-Origin`)
|
||||
based on the CORS configuration you have provided.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
Be aware that cookies are not allowed by default to avoid increasing the surface attack of
|
||||
the web application (for example via exposing sensitive user-specific information like
|
||||
CSRF tokens). Set `allowedCredentials` property to `true` in order to allow them.
|
||||
====
|
||||
|
||||
|
||||
[[webflux-cors-controller]]
|
||||
== @CrossOrigin
|
||||
|
@ -146,7 +153,7 @@ public class WebConfig implements WebFluxConfigurer {
|
|||
.allowedMethods("PUT", "DELETE")
|
||||
.allowedHeaders("header1", "header2", "header3")
|
||||
.exposedHeaders("header1", "header2")
|
||||
.allowCredentials(false).maxAge(3600);
|
||||
.allowCredentials(true).maxAge(3600);
|
||||
}
|
||||
}
|
||||
----
|
||||
|
|
|
@ -27,6 +27,13 @@ implementation (https://github.com/spring-projects/spring-framework/blob/master/
|
|||
by default) in order to add the relevant CORS response headers (like `Access-Control-Allow-Origin`)
|
||||
based on the CORS configuration you have provided.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
Be aware that cookies are not allowed by default to avoid increasing the surface attack of
|
||||
the web application (for example via exposing sensitive user-specific information like
|
||||
CSRF tokens). Set `allowedCredentials` property to `true` in order to allow them.
|
||||
====
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
Since CORS requests are automatically dispatched, you *do not need* to change the
|
||||
|
@ -165,7 +172,7 @@ public class WebConfig implements WebMvcConfigurer {
|
|||
.allowedMethods("PUT", "DELETE")
|
||||
.allowedHeaders("header1", "header2", "header3")
|
||||
.exposedHeaders("header1", "header2")
|
||||
.allowCredentials(false).maxAge(3600);
|
||||
.allowCredentials(true).maxAge(3600);
|
||||
}
|
||||
}
|
||||
----
|
||||
|
@ -197,7 +204,7 @@ It is also possible to declare several CORS mappings with customized properties:
|
|||
allowed-origins="http://domain1.com, http://domain2.com"
|
||||
allowed-methods="GET, PUT"
|
||||
allowed-headers="header1, header2, header3"
|
||||
exposed-headers="header1, header2" allow-credentials="false"
|
||||
exposed-headers="header1, header2" allow-credentials="true"
|
||||
max-age="123" />
|
||||
|
||||
<mvc:mapping path="/resources/**"
|
||||
|
|
Loading…
Reference in New Issue