出于安全考虑,浏览器禁止对当前源以外的资源进行AJAX调用。例如,当你在一个标签页检查你的银行帐户时,你能够在另外一个标签页打开evil.com的网站。在evil.com中的脚本不能使用你的凭据来经过AJAX请求访问你的银行API(例如,从你的银行取款!)。html
跨域资源共享(Cross-origin resource sharing)(CORS)是W3C的标准,大部分的浏览器都实现了这个标准来让你能够灵活地指定什么样的跨域请求是被受权的,而不用使用IFRAME或JSONP这些不太安全和功能不强的黑客技术。java
从Spring Framework 4.2起,CORS就支持开箱即用。CORS请求(包括一个预检请求OPTIONS方法)自动分发到各个注册的HandlerMapping
中。因为CorsProcessor的实现(默认是DefaultCorsProcessor),它们处理CORS预检请求,并拦截CORS的简单而实际请求,以便根据你提供的CORS配置添加相关的CORS响应头(如Access-Control-Allow-Origin
)。git
因为CORS请求是自动分发的,你不须要改变
DispatcherServlet
dispatchOptionsRequest
的初始参数值;推荐的方式是使用它的默认值(false)。github
你能够在你的@RequestMapping
注解处理方法上添加一个@CrossOrigin
注解来开启CORS。默认@CrossOrigin
容许全部的源和在@RequestMapping
注解上指定的HTTP方法:web
@RestController @RequestMapping("/account") public class AccountController { @CrossOrigin @RequestMapping("/{id}") public Account retrieve(@PathVariable Long id) { // ... } @RequestMapping(method = RequestMethod.DELETE, path = "/{id}") public void remove(@PathVariable Long id) { // ... } }
它也能够在全部的控制器上开启CORS:spring
@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, path = "/{id}") public void remove(@PathVariable Long id) { // ... } }
在上面的例子中,对retrieve()
和remove()
处理方法都开启了CORS支持,你也能够看到你能够经过@CrossOrigin
的属性来配置CORS。api
你甚至能够在控制器级别和方法级别进行CORS配置。Spring将组合两个注解的属性来建立一个组合的CORS配置。跨域
@CrossOrigin(maxAge = 3600) @RestController @RequestMapping("/account") public class AccountController { @CrossOrigin("http://domain2.com") @RequestMapping("/{id}") public Account retrieve(@PathVariable Long id) { // ... } @RequestMapping(method = RequestMethod.DELETE, path = "/{id}") public void remove(@PathVariable Long id) { // ... } }
除了基于注解的细粒度配置,你也可能想要定义一些全局的CORS配置。这个与使用过滤器相似,可是能够在Spring MVC中声明跟加上@CrossOrigin
的细粒度配置。默认是容许全部的源跟GET
,HEAD
和POST
方法。浏览器
整个应用开启CORS的例子以下:安全
@Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**"); } }
你能够轻松地改变任何属性,也能够将CORS配置指定到特殊的路径模式:
@Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer { @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配置能够在/**
路径模式下开启CORS,具备跟前文提到的JavaConfig同样的缺省属性,例子:
<mvc:cors> <mvc:mapping path="/**" /> </mvc:cors>
它还能够用定制的属性来指定多个CORS映射:
<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>
CorsConfiguration容许你指定CORS请求如何被处理:容许的源,头信息,方法等等。它能够以多种方式提供:
AbstractHandlerMapping#setCorsConfiguration()
容许经过一个有一些CorsConfiguration实例的Map
来指定映射到如/api/**
的路径模式上。AbstractHandlerMapping#getCorsConfiguration(Object, HttpServletRequest)
方法来提供它们的CorsConfiguration
。CorsConfigurationSource
接口(如ResourceHttpRequestHandler如今作的)。为了实现如Spring Security的基于过滤器的安全框架去支持CORS,或其余原生不支持CORS的类库,Spring框架也提供了CorsFilter。而不是使用@CrossOrigin
或WebMvcConfigurer#addCorsMappings(CorsRegistry)
,你须要注册一个以下的自定义过滤器:
import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; public class MyCorsFilter extends CorsFilter { public MyCorsFilter() { super(configurationSource()); } private static UrlBasedCorsConfigurationSource configurationSource() { CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); config.addAllowedOrigin("http://domain1.com"); config.addAllowedHeader("*"); config.addAllowedMethod("*"); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", config); return source; } }
你须要确保CorsFilter
在其余过滤器以前,相应地看一下关于如何配置Spring Boot的这篇博客。
【译者注】 原文:http://docs.spring.io/spring/docs/5.0.0.RC1/spring-framework-reference/web.html#cors 看这篇文章以前,建议看一下阮一峰写的关于CORS的文章 欢迎批评指正