該文章轉(zhuǎn)至SpringBoot官網(wǎng) http://spring.io/blog/2015/06/08/cors-support-in-spring-framework
現(xiàn)在開發(fā)的項目一般都是前后端分離的項目,所以跨域訪問會經(jīng)常使用冠蒋。
出于安全原因值朋,瀏覽器禁止對駐留在當(dāng)前源之外的資源進行AJAX調(diào)用廊勃。例如较店,當(dāng)您在一個標(biāo)簽中檢查您的銀行帳戶時释树,您可以將evil.com網(wǎng)站放在另一個標(biāo)簽中杂穷。來自evil.com的腳本不能使用您的憑據(jù)向您的銀行API(從您的帳戶中提取資金W茵)發(fā)出AJAX請求拾碌。
跨源資源共享(CORS)是大多數(shù)瀏覽器實現(xiàn)的W3C規(guī)范,允許您以靈活的方式指定授權(quán)的跨域請求類型街望,而不是使用IFrame或JSONP等安全性較低且功能較弱的黑客校翔。
Spring Framework 4.2 GA為開箱即用的CORS提供了一流的支持,為您提供了比典型的基于過濾器的解決方案更簡單灾前,更強大的配置方式防症。
Spring MVC提供了高級配置工具,如下所述哎甲。
控制器方法CORS配置
您可以在@RequestMapping
注釋的處理程序方法中添加@CrossOrigin
注釋蔫敲,以便在其上啟用CORS(默認(rèn)情況下@CrossOrigin
允許@RequestMapping
注釋中指定的所有源和HTTP方法):
@RestController
@RequestMapping("/account")
public class AccountController {
@CrossOrigin
@GetMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}
@DeleteMapping("/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}
也可以為整個控制器啟用CORS:
@CrossOrigin(origins = "http://domain2.com", maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {
@GetMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}
@DeleteMapping("/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}
在此示例中,為兩個retrieve()
和remove()
處理程序方法啟用了CORS支持炭玫,您還可以了解如何使用@CrossOrigin
屬性自定義CORS配置奈嘿。
您甚至可以使用控制器和方法級別的CORS配置,然后Spring將組合兩個注釋屬性以創(chuàng)建合并的CORS配置吞加。
@CrossOrigin(maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {
@CrossOrigin(origins = "http://domain2.com")
@GetMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}
@DeleteMapping("/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}
如果您使用的是Spring Security裙犹,請確保在Spring Security級別啟用CORS,以允許它利用Spring MVC級別定義的配置榴鼎。
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and()...
}
}
全局CORS配置
除了細(xì)粒度的基于注釋的配置之外伯诬,您可能還需要定義一些全局CORS配置晚唇。這類似于使用過濾器巫财,但可以使用Spring MVC聲明并結(jié)合細(xì)粒度@CrossOrigin
配置。默認(rèn)情況下GET
哩陕,允許所有原點HEAD
和POST
方法平项。
JavaConfig
為整個應(yīng)用程序啟用CORS非常簡單:
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
}
如果您使用的是Spring Boot,建議您將WebMvcConfigurer
bean 聲明如下:
@Configuration
public class MyConfiguration {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
};
}
}
您可以輕松更改任何屬性悍及,并僅將此CORS配置應(yīng)用于特定路徑模式:
@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);
}
如果您使用的是Spring Security闽瓢,請確保在Spring Security級別啟用CORS,以允許它利用Spring MVC級別定義的配置心赶。
XML命名空間
也可以使用mvc XML名稱空間配置CORS 扣讼。
這種最小的XML配置在/**
路徑模式上啟用CORS ,其默認(rèn)屬性與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>
如果您使用的是Spring Security缨叫,請不要忘記在Spring Security級別啟用CORS:
<http>
<!-- Default to Spring MVC's CORS configuration -->
<cors />
...
</http>
它是如何工作的?
CORS請求(包括帶有OPTIONS
方法的預(yù)檢)會自動發(fā)送到各個HandlerMapping
已注冊的請求。由于CorsProcessor實現(xiàn)(默認(rèn)情況下為DefaultCorsProcessor),它們處理CORS預(yù)檢請求并攔截CORS簡單和實際請求似忧,以便添加相關(guān)的CORS響應(yīng)頭(如Access-Control-Allow-Origin
)诗箍。CorsConfiguration允許您指定如何處理CORS請求:允許的起源,標(biāo)題匠童,方法等汤求。它可以以各種方式提供:
-
AbstractHandlerMapping#setCorsConfiguration()
允許指定一個映射在路徑模式上的Map
幾個CorsConfiguration/api/**
- 子類可以
CorsConfiguration
通過重寫AbstractHandlerMapping#getCorsConfiguration(Object, HttpServletRequest)
方法提供自己的子類 - 處理程序可以實現(xiàn)
CorsConfigurationSource
接口(就像ResourceHttpRequestHandler
現(xiàn)在一樣)挤牛,以便為每個請求提供CorsConfiguration。
基于過濾器的CORS支持
作為上述其他方法的替代方案诫硕,Spring Framework還提供了CorsFilter。在這種情況下,您可以在Spring Boot應(yīng)用程序中聲明過濾器翰舌,而不是使用@CrossOrigin
或WebMvcConfigurer#addCorsMappings(CorsRegistry)
:
@Configuration
public class MyConfiguration {
@Bean
public FilterRegistrationBean corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("http://domain1.com");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
bean.setOrder(0);
return bean;
}
}