Add CORS section to the ref doc

This commit is contained in:
Sebastien Deleuze 2015-06-29 15:15:16 +02:00
parent c9b26d80e1
commit b439402d57
2 changed files with 203 additions and 0 deletions

201
src/asciidoc/web-cors.adoc Normal file
View File

@ -0,0 +1,201 @@
[[cors]]
= CORS Support
== Introduction
For security reasons, browsers prohibit AJAX calls to resources residing outside the
current origin. For example, as you're checking your bank account in one tab, you
could have the evil.com website in another tab. The scripts from evil.com should not
be able to make AJAX requests to your bank API (withdrawing money from your account!)
using your credentials.
http://en.wikipedia.org/wiki/Cross-origin_resource_sharing[Cross-origin resource sharing]
(CORS) is a http://www.w3.org/TR/cors/[W3C specification] implemented by
http://caniuse.com/#feat=cors[most browsers] that allows you to specify in a flexible
way what kind of cross domain requests are authorized, instead of using some less secured
and less powerful hacks like IFrame or JSONP.
As of Spring Framework 4.2, CORS is supported out of the box. CORS requests
(https://github.com/spring-projects/spring-framework/blob/master/spring-webmvc/src/main/java/org/springframework/web/servlet/FrameworkServlet.java#L906[including preflight ones with an `OPTIONS` method])
are automatically dispatched to the various `HandlerMapping` registered. They handle
CORS preflight requests and intercept CORS simple and actual requests thanks to a
http://docs.spring.io/spring/docs/4.2.x/javadoc-api/org/springframework/web/cors/CorsProcessor.html[CorsProcessor]
implementation (https://github.com/spring-projects/spring-framework/blob/master/spring-web/src/main/java/org/springframework/web/cors/DefaultCorsProcessor.java[DefaultCorsProcessor]
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]
====
Since CORS requests are automatically dispatched, you *do not need* to change
`DispatcherServlet` `dispatchOptionsRequest` init parameter value, using its default value
(`false`) is the recommended approach.
====
== Controller method CORS configuration
You can add to your `@RequestMapping` annotated handler method a
http://docs.spring.io/spring/docs/4.2.x/javadoc-api/org/springframework/web/bind/annotation/CrossOrigin.html[`@CrossOrigin`]
annotation in order to enable CORS on it (by default `@CrossOrigin` allows all origins
and the HTTP methods specified in the `@RequestMapping` annotation):
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@RestController
@RequestMapping("/account")
public class AccountController {
@CrossOrigin
@RequestMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}
@RequestMapping(method = RequestMethod.DELETE, value = "/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}
----
It is also possible to enable CORS for the whole controller:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@CrossOrigin(origins = "http://domain2.com", maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {
@RequestMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}
@RequestMapping(method = RequestMethod.DELETE, value = "/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}
----
In this example CORS support is enabled for both `retrieve()` and `remove()` handler methods, and you can also see how you can customize the CORS configuration using `@CrossOrigin` attributes.
You can even use both controller and method level CORS configurations, Spring will then combine both annotation attributes to create a merged CORS configuration.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@CrossOrigin(maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {
@CrossOrigin(origins = "http://domain2.com")
@RequestMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}
@RequestMapping(method = RequestMethod.DELETE, value = "/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}
----
== Global CORS configuration
In addition to fine-grained, annotation-based configuration you'll probably want to
define some global CORS configuration as well. This is similar to using filters but can
be declared withing Spring MVC and combined with fine-grained `@CrossOrigin` configuration.
By default all origins and `GET`, `HEAD` and `POST` methods are allowed.
=== JavaConfig
Enabling CORS for the whole application is as simple as:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
}
----
You can easily change any properties, as well as only apply this CORS configuration to a
specific path pattern:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://domain2.com")
.allowedMethods("PUT", "DELETE")
.allowedHeaders("header1", "header2", "header3")
.exposedHeaders("header1", "header2")
.allowCredentials(false).maxAge(3600);
}
}
----
=== XML namespace
This minimal XML configuration enable CORS on `/**` path pattern with the same default properties than the JavaConfig one:
[source,xml,indent=0]
[subs="verbatim"]
----
<mvc:cors>
<mvc:mapping path="/**" />
</mvc:cors>
----
It is also possible to declare several CORS mappings with customized properties:
[source,xml,indent=0]
[subs="verbatim"]
----
<mvc:cors>
<mvc:mapping path="/api/**"
allowed-origins="http://domain1.com, http://domain2.com"
allowed-methods="GET, PUT"
allowed-headers="header1, header2, header3"
exposed-headers="header1, header2" allow-credentials="false"
max-age="123" />
<mvc:mapping path="/resources/**"
allowed-origins="http://domain1.com" />
</mvc:cors>
----
== Advanced Customizations
http://docs.spring.io/spring/docs/4.2.x/javadoc-api/org/springframework/web/cors/CorsConfiguration.html[CorsConfiguration]
allows you to specify how the CORS requests should be processed: allowed origins, headers, methods, etc.
It can be provided in various ways:
* http://docs.spring.io/spring/docs/4.2.x/javadoc-api/org/springframework/web/servlet/handler/AbstractHandlerMapping.html#setCorsConfiguration-java.util.Map-[`AbstractHandlerMapping#setCorsConfiguration()`]
allows to specify a `Map` with several http://docs.spring.io/spring/docs/4.2.x/javadoc-api/org/springframework/web/cors/CorsConfiguration.html[CorsConfiguration]
mapped on path patterns like `/api/**`
* Subclasses can provide their own `CorsConfiguration` by overriding
`AbstractHandlerMapping#getCorsConfiguration(Object, HttpServletRequest)` method
* Handlers can implement http://docs.spring.io/spring/docs/4.2.x/javadoc-api/org/springframework/web/cors/CorsConfigurationSource.html[`CorsConfigurationSource`]
interface (like https://github.com/spring-projects/spring-framework/blob/master/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java[`ResourceHttpRequestHandler`]
now does) in order to provide a http://docs.spring.io/spring/docs/4.2.x/javadoc-api/org/springframework/web/cors/CorsConfiguration.html[CorsConfiguration]
for each request.

View File

@ -32,3 +32,5 @@ include::web-integration.adoc[leveloffset=+1]
include::web-portlet.adoc[leveloffset=+1]
include::web-websocket.adoc[leveloffset=+1]
include::web-cors.adoc[leveloffset=+1]