出於安全考慮,瀏覽器禁止對當前源以外的資源進行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的文章 歡迎批評指正