首页 > 代码库 > Spring 4 官方文档学习(十五)CORS支持
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
Spring 4 官方文档学习(十五)CORS支持