Spring MVC使您可以处理CORS(跨域资源共享)。本节介绍如何执行此操作。
出于安全原因,浏览器禁止AJAX调用当前来源以外的资源。例如,您可以将您的银行帐户放在一个标签中,将evil.com放在另一个标签中。来自evil.com的脚本不能使用您的凭据向您的银行API发出AJAX请求,例如从您的帐户中提取资金!
跨域资源共享(CORS)是大多数浏览器实施的W3C规范,可让您指定授权哪种类型的跨域请求,而不是使用基于IFRAME或JSONP的安全性较低且功能较弱的变通办法。
CORS规范区分飞行前,简单和实际请求。要了解CORS的工作原理,您可以阅读本文以及其他内容,或者参阅规范以获取更多详细信息。
Spring MVC HandlerMapping实现为CORS提供内置支持。成功将请求映射到处理程序后,HandlerMapping实现将检查给定请求和处理程序的CORS配置,并采取进一步的措施。飞行前请求直接处理,而简单和实际的CORS请求被拦截,验证并设置了必需的CORS响应标头。
为了启用跨域请求(即存在Origin标头,并且与请求的主机不同),您需要具有一些显式声明的CORS配置。如果找不到匹配的CORS配置,则预检请求将被拒绝。没有将CORS标头添加到简单和实际CORS请求的响应中,因此,浏览器拒绝了它们。
可以使用基于URL模式的CorsConfiguration映射分别配置每个HandlerMapping。在大多数情况下,应用程序使用MVC Java配置或XML名称空间声明此类映射,这导致将单个全局映射传递给所有HandlerMappping实例。
您可以将HandlerMapping级别的全局CORS配置与更细粒度的处理程序级别的CORS配置结合使用。例如,带注解的控制器可以使用类或方法级别的@CrossOrigin注解(其他处理程序可以实现CorsConfigurationSource)。
全局和本地配置组合的规则通常是相加的,例如,所有全局和所有本地起源。对于只能接受单个值的那些属性(例如allowCredentials和maxAge),局部属性将覆盖全局值。有关更多详细信息,请参见CorsConfiguration#combine(CorsConfiguration)。
@CrossOrigin批注启用带注解的控制器方法上的跨域请求,如以下示例所示:
@RestController
@RequestMapping("/account")
public class AccountController {
@CrossOrigin
@GetMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}
@DeleteMapping("/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}
默认情况下,@ CrossOrigin允许:
- All origins.
- All headers.
- 控制器方法映射到的所有HTTP方法。
默认情况下,allowedCredentials未启用,因为它建立了一个信任级别,可以公开敏感的用户特定信息(例如cookie和CSRF令牌),并且仅在适当的地方使用。
maxAge设置为30分钟。
@CrossOrigin在类级别上也受支持,并且被所有方法继承,如以下示例所示:
@CrossOrigin(origins = "https://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) {
// ...
}
}
您可以在类级别和方法级别上使用@CrossOrigin,如以下示例所示:
@CrossOrigin(maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {
@CrossOrigin("https://domain2.com")
@GetMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}
@DeleteMapping("/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}
除了细粒度的控制器方法级别配置外,您可能还想定义一些全局CORS配置。 您可以在任何HandlerMapping上分别设置基于URL的CorsConfiguration映射。 但是,大多数应用程序使用MVC Java配置或MVC XNM命名空间来执行此操作。
默认情况下,全局配置启用以下功能:
- All origins.
- All headers.
- GET,HEAD和POST方法。
默认情况下,allowedCredentials未启用,因为它建立了一个信任级别,可以公开敏感的用户特定信息(例如cookie和CSRF令牌),并且仅在适当的地方使用。
maxAge设置为30分钟。
Java Configuration
要在MVC Java配置中启用CORS,可以使用CorsRegistry回调,如以下示例所示:
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("https://domain2.com")
.allowedMethods("PUT", "DELETE")
.allowedHeaders("header1", "header2", "header3")
.exposedHeaders("header1", "header2")
.allowCredentials(true).maxAge(3600);
// Add more mappings...
}
}
XML Configuration
要在XML名称空间中启用CORS,可以使用<mvc:cors>元素,如以下示例所示:
<mvc:cors>
<mvc:mapping path="/api/**"
allowed-origins="https://domain1.com, https://domain2.com"
allowed-methods="GET, PUT"
allowed-headers="header1, header2, header3"
exposed-headers="header1, header2" allow-credentials="true"
max-age="123" />
<mvc:mapping path="/resources/**"
allowed-origins="https://domain1.com" />
</mvc:cors>
您可以通过内置的CorsFilter应用CORS支持。
如果您尝试将CorsFilter与Spring Security一起使用,请记住Spring Security内置了对CORS的支持。
要配置过滤器,请将CorsConfigurationSource传递给其构造函数,如以下示例所示:
CorsConfiguration config = new CorsConfiguration();
// Possibly...
// config.applyPermitDefaultValues()
config.setAllowCredentials(true);
config.addAllowedOrigin("https://domain1.com");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
CorsFilter filter = new CorsFilter(source);