Spring 4 官方文檔學習(十五)CORS支持


1、介紹

由於安全原因,瀏覽器禁止AJAX請求不在當前域內的資源。例如,你在一個瀏覽器標簽中檢查你的銀行賬戶時,可能在另一個標簽中打開了evil.com 。來自evil.com的腳本絕對不可以用AJAX請求你的銀行API!

 

Cross-origin resource sharing (CORS) 是一個W3C specification,大多數瀏覽器都已經實現了該功能,可以讓你以一種彈性的方式指定哪些跨域請求是被授權的,而不是用一些不怎么安全或不怎么強大的手段 -- 如IFRAME或JSONP。

 

自Spring Framework 4.2開始,CORS已經可以開箱即用啦。CORS請求(包括OPTIONS method)會被自動分發到各種注冊過的HandlerMappings。它們會處理CORS的preflight請求,會攔截CORS簡單和實際請求 -- 這都是CorsProcessor的一個實現的功勞(默認是DefaultCorsProcessor),以便添加相關的CORS響應頭(如 Access-Control-Allow-Origin) -- 基於你提供的CORS配置。

 

注意:因為CORS請求會被自動分發,所以你不需要改變DispatcherServlet dispatchOptionsRequest 的 init parameter值;其默認值(false)就可以!

 

2、Controller method CORS configuration -- Controller方法的CORS配置

你可以在你的@RequestMapping注解過的controller method上面添加@CrossOrigin注解,已開啟CORS。默認,該注解允許@RequestMapping中指定的所有原始域和HTTP methods。如下:

@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) {
        // ...
    }
}

也可以為整個controller啟用CORS:

@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的attributes來定制CORS配置。

 

還可以同時使用controller級別和method級別的CORS配置;Spring會將二者的attributes結合起來,創建出融合的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) {
        // ...
    }
}

-- 不要懵,就是正常的請求,只不過是從別的域中發起的。

 

3、全局CORS配置

除了細粒度的、基於注解的配置,還可以定義全局的CORS配置。類似於使用filters,但可以定義在Spring MVC中,並與細粒度的@CrossOrigin配置相配合。 默認,允許所有的origins和GET、HEAD、POST methods。

 

3.1、JavaConfig

開啟全局的CORS是很簡單的:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**");
    }
}

你可以輕松的修改任何properties,也可以將CORS配置應用到某個特定的path pattern:

@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);
    }
}

 

3.2、XML namespace

<mvc:cors>
    <mvc:mapping path="/**" />
</mvc: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>

 

4、高級定制

CorsConfiguration允許指定如何處理CORS請求:allowed origins、headers、methods等等。

有多種方式實現:

AbstractHandlerMapping#setCorsConfiguration()允許指定一個Map,然后在Map中封入幾個CorsConfiguration實例 -- 映射到path patterns,如 /api/** 。

重寫AbstractHandlerMapping#getCorsConfiguration(Object, HttpServletRequest)即可提供自己的CorsConfiguration 。

handlers可以實現CorsConfigurationSource接口,從而為每個請求提供一個CorsConfiguration實例。--ResourceHttpRequestHandler已經實現了該接口。

 

5、基於filter的CORS支持

為了在基於filter的安全框架--如Spring Security上面支持CORS,或者在使用其他不支持CORS的庫上支持CORS,Spring框架還提供了一個CorsFilter。不過這樣的話,就不能使用@CrossOrigin 或者 WebMvcConfigurer#addCorsMappings(CorsRegistry)了,需要注冊一個自定義的filter:

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的順序先於所有其他的filters,見this blog post,是關於如何配置Spring Boot的。

 

 

 

推薦個鏈接:

跨域資源共享 CORS 詳解 

這里

 

官方鏈接地址:

http://docs.spring.io/spring/docs/current/spring-framework-reference/html/cors.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM