On this page
27. CORS Support
27.1 Introduction
出于安全原因,浏览器禁止 AJAX 调用当前来源之外的资源。例如,当您在一个标签中检查银行帐户时,可以在另一个标签中打开 evil.com 网站。 evil.com 的脚本不能使用您的凭据向您的银行 API 发出 AJAX 请求(例如,从您的帐户中提取资金!)。
跨域资源共享(CORS)是由most browsers实现的W3C specification,它使您可以灵活地指定对哪种跨域请求进行授权,而不必使用诸如 IFRAME 或 JSONP 之类的安全性较低且功能较弱的黑客。
从 Spring Framework 4.2 开始,开箱即用地支持 CORS。 CORS 请求(使用 OPTIONS 方法包括预检)被自动分派到各个已注册的HandlerMapping
。由于使用了CorsProcessor实现(默认为DefaultCorsProcessor),它们可以处理 CORS 预检请求并拦截 CORS 简单和实际的请求,以便根据您提供的 CORS 配置添加相关的 CORS 响应 Headers(如Access-Control-Allow-Origin
)。
Note
由于 CORS 请求是自动分派的,因此您 无需 更改DispatcherServlet
dispatchOptionsRequest
初始化参数值;建议使用其默认值(false
)。
27.2 控制器方法 CORS 配置
您可以将@CrossOriginComments 添加到带有@RequestMapping
Comments 的处理程序方法中,以便在其上启用 CORS。默认情况下,@CrossOrigin
允许所有来源和@RequestMapping
注解中指定的 HTTP 方法:
@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:
@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 配置。
您甚至可以同时使用控制器级别和方法级别的 CORS 配置。然后,Spring 将结合两个 Comments 中的属性来创建合并的 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) {
// ...
}
}
27.3 全局 CORS 配置
除了基于 Comments 的细粒度配置之外,您可能还需要定义一些全局 CORS 配置。这类似于使用过滤器,但是可以在 Spring MVC 中声明并与细粒度的@CrossOrigin
配置结合使用。默认情况下,所有原点以及GET
,HEAD
和POST
方法都是允许的。
27.3.1 JavaConfig
为整个应用程序启用 CORS 很简单:
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
}
您可以轻松更改任何属性,以及仅将此 CORS 配置应用于特定的路径模式:
@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);
}
}
27.3.2 XML 名称空间
以下最低限度的 XML 配置使/**
路径模式的 CORS 具有与上述 JavaConfig 示例相同的默认属性:
<mvc:cors>
<mvc:mapping path="/**" />
</mvc:cors>
也可以使用自定义属性声明几个 CORSMap:
<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>
27.4 高级定制
CorsConfiguration允许您指定应如何处理 CORS 请求:允许的来源,Headers,方法等。可以通过多种方式提供:
AbstractHandlerMapping#setCorsConfiguration()允许指定
Map
,其中几个CorsConfiguration实例 Map 到/api/**
之类的路径模式。子类可以通过覆盖
AbstractHandlerMapping#getCorsConfiguration(Object, HttpServletRequest)
方法来提供自己的CorsConfiguration
。处理程序可以实现CorsConfigurationSource接口(现在像ResourceHttpRequestHandler一样),以便为每个请求提供CorsConfiguration实例。
27.5 基于过滤器的 CORS 支持
为了使用诸如Spring Security之类的基于过滤器的安全框架来支持 CORS,或者使用其他本机不支持 CORS 的库来支持 CORS,Spring Framework 还提供了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;
}
}
您需要确保在其他过滤器之前 Order 了CorsFilter
,有关如何相应配置 Spring Boot 的信息,请参见此博客文章。