標籤:

Spring之CROS解決AJAX跨域問題

說明

  1. 出於安全考慮,瀏覽器禁止AJAX調用駐留在當前來源之外的資源。例如,當您在一個標籤中檢查您的銀行帳戶時,您可以將evil.com網站放在另一個標籤中。evil.com的腳本不能使用您的憑據向您的銀行API發出AJAX請求(從您的帳戶中提款)!
  2. 跨原始資源共享(CORS)是大多數瀏覽器實現的W3C規範,允許您以靈活的方式指定什麼樣的跨域請求被授權,而不是使用一些不太安全和不太強大的黑客,如IFrame或JSONP。
  3. Spring Framework 4.2 GA為開箱即用的CORS提供了一流的支持,為您提供了比典型的基於過濾器的解決方案更簡單和更強大的配置方式。

Spring MVC提供了高級配置功能

控制器方法CORS配置

您可以向@RequestMapping注釋處理程序方法添加@CrossOrigin注釋,以便啟用CORS(默認情況下@CrossOrigin允許@RequestMapping注釋中指定的所有起始和HTTP方法):

@RestControllern @RequestMapping("/account")n public class AccountController {nn @CrossOriginn @GetMapping("/{id}")n public Account retrieve(@PathVariable Long id) {n // ...n }nn @DeleteMapping("/{id}")n public void remove(@PathVariable Long id) {n // ...n }n

也可以為整個控制器啟用CORS:

@CrossOrigin(origins = "http://domain2.com", maxAge = 3600)n @RestControllern @RequestMapping("/account")n public class AccountController {nn @GetMapping("/{id}")n public Account retrieve(@PathVariable Long id) {n // ...n }nn @DeleteMapping("/{id}")n public void remove(@PathVariable Long id) {n // ...n }n }n

在此示例中,對於這兩種方法retrieve()remove()處理程序方法都啟用了CORS支持,還可以看到如何使用@CrossOrigin屬性自定義CORS配置。

您甚至可以同時使用控制器和方法級CORS配置,然後Spring將組合兩個注釋屬性來創建合併的CORS配置。

@CrossOrigin(maxAge = 3600)n@RestControllern@RequestMapping("/account")npublic class AccountController {nn @CrossOrigin(origins = "http://domain2.com")n @GetMapping("/{id}")n public Account retrieve(@PathVariable Long id) {n // ...n }nn @DeleteMapping("/{id}")n public void remove(@PathVariable Long id) {n // ...n }n}n

如果您使用Spring Security,請確保在Spring Security級別啟用CORS,並允許它利用Spring MVC級別定義的配置。

@EnableWebSecuritynpublic class WebSecurityConfig extends WebSecurityConfigurerAdapter {nn @Overriden protected void configure(HttpSecurity http) throws Exception {n http.cors().and()...n }n}n

全局CORS配置

除了細粒度的基於注釋的配置,您也可能想要定義一些全局CORS配置。這與使用過濾器類似,但可以使用Spring MVC聲明並結合細粒度@CrossOrigin配置。默認情況下,所有的起源和GETHEADPOST方法都是允許的。

JavaConfig

為整個應用程序啟用CORS類似於

@Configurationn @EnableWebMvcn public class WebConfig extends WebMvcConfigurerAdapter {nn @Overriden public void addCorsMappings(CorsRegistry registry) {n registry.addMapping("/**");n }n }n

如果您使用的是Spring Boot,建議只要聲明一個WebMvcConfigurerbean如下:

@Configurationnpublic class MyConfiguration {nn @Beann public WebMvcConfigurer corsConfigurer() {n return new WebMvcConfigurerAdapter() {n @Overriden public void addCorsMappings(CorsRegistry registry) {n registry.addMapping("/**");n }n };n }n} n

您可以輕鬆地更改任何屬性,以及僅將此CORS配置應用於特定路徑模式:

@Overridenpublic void addCorsMappings(CorsRegistry registry) {n registry.addMapping("/api/**")n .allowedOrigins("http://domain2.com")n .allowedMethods("PUT", "DELETE")n .allowedHeaders("header1", "header2", "header3")n .exposedHeaders("header1", "header2")n .allowCredentials(false).maxAge(3600);n}n

如果您使用Spring Security,請確保在Spring Security級別啟用CORS,並允許它利用Spring MVC級別定義的配置。

XML命名空間

也可以使用mvc XML命名空間配置CORS 。

這種最小的XML配置使得/**路徑模式上的CORS 具有與JavaConfig相同的默認屬性:

<mvc:cors>n <mvc:mapping path="/**" />n</mvc:cors>n

也可以使用自定義屬性聲明幾個CORS映射:

<mvc:cors>nn <mvc:mapping path="/api/**"n allowed-origins="http://domain1.com, http://domain2.com"n allowed-methods="GET, PUT"n allowed-headers="header1, header2, header3"n exposed-headers="header1, header2" allow-credentials="false"n max-age="123" />nn <mvc:mapping path="/resources/**"n allowed-origins="http://domain1.com" />nn</mvc:cors>n

如果您使用Spring Security,請不要忘記在Spring Security級別啟用CORS:

<http>n <!-- Default to Spring MVCs CORS configuration -->n <cors />n ...n</http>n

它是如何工作的?

CORS請求(ref="github.com/spring-proje">包括帶有OPTIONS方法的預檢)請求被自動發送到已HandlerMapping註冊的各種。他們處理CORS預檢要求和攔截CORS簡單而實際的請求得益於CorsProcessor實現(DefaultCorsProcessor以添加相關CORS響應頭(如默認情況下)Access-Control-Allow-Origin)。CorsConfiguration允許您指定如何處理CORS請求:允許的起點,頭,方法等。它可以以各種方式提供:

  1. AbstractHandlerMapping#setCorsConfiguration()允許在路徑模式上映射Map幾個CorsConfiguration來指定一個/api/**
  2. 子類可以CorsConfiguration通過重寫AbstractHandlerMapping#getCorsConfiguration(Object, HttpServletRequest)方法提供自己的子類
  3. 處理程序可以實現CorsConfigurationSource介面(像ResourceHttpRequestHandler現在這樣),以便為每個請求提供CorsConfiguration。

基於過濾器的CORS支持

作為上述其他方法的替代方法,Spring Framework還提供了一個CorsFilter。在這種情況下,而不是使用@CrossOrigin或者WebMvcConfigurer#addCorsMappings(CorsRegistry)您可以例如在Spring Boot應用程序中聲明過濾器如下:

@Configurationnpublic class MyConfiguration {nn @Beann public FilterRegistrationBean corsFilter() {n UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();n CorsConfiguration config = new CorsConfiguration();n config.setAllowCredentials(true);n config.addAllowedOrigin("http://domain1.com");n config.addAllowedHeader("*");n config.addAllowedMethod("*");n source.registerCorsConfiguration("/**", config);n FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));n bean.setOrder(0);n return bean;n }n}n

原文 :Spring之CROS解決AJAX跨域問題 | Spring For All

推薦閱讀:

怎樣合理地使用 Ajax ?過度使用 Ajax 會有哪些弊端?
115登錄頁的long polling在chrome裡面為什麼看不到返回結果?
jquery ajax怎麼通過header傳遞參數? 不想通過url傳參!
如何解决 Ajax 跨域请求不到的问题?
js 詞法作用域(靜態) 與 作用域鏈 指向 活動對象(動態--執行) 不矛盾嗎?

TAG:Spring | Ajax |