27. CORS支持

27.1 简介

出于安全原因,浏览器禁止对驻留在当前源之外的资源进行AJAX调用。例如,当您在一个标签中检查您的银行帐户时,您可以在另一个标签中打开evil.com网站。来自evil.com的脚本不能使用您的凭据向您的银行API发出AJAX请求(例如,从您的帐户中提款!)。

Cross-origin resource sharing (CORS)是由 most browsers 实现的 W3C specification ,它允许您以灵活的方式指定授权哪种类型的跨域请求,而不是使用一些安全性较低且功能较弱的黑客,如IFRAME或JSONP。

从Spring Framework 4.2开始,CORS支持开箱即用。 CORS请求( including preflight ones with an OPTIONS method )会自动分派到各个已注册的 HandlerMapping 。由于 CorsProcessor 实现(默认为 DefaultCorsProcessor ),它们处理CORS预检请求并拦截CORS简单和实际请求,以便根据您提供的CORS配置添加相关的CORS响应头(如 Access-Control-Allow-Origin )。

由于自动调度CORS请求,因此您无需更改DispatcherServlet dispatchOptionsRequest init参数值;建议使用其默认值(false)做法。

27.2 控制器方法CORS配置

您可以在 @RequestMapping 带注释的处理程序方法中添加 @CrossOrigin 注释,以便在其上启用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将组合来自两个注释的属性以创建合并的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配置

除了细粒度,基于注释的配置之外,您可能还需要定义一些全局CORS配置。这与使用过滤器类似,但可以在Spring MVC中声明,并与细粒度的 @CrossOrigin 配置相结合。默认情况下,允许使用所有原点和 GETHEADPOST 方法。

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>

也可以使用自定义属性声明多个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>

27.4 高级自定义

CorsConfiguration 允许您指定如何处理CORS请求:允许的起源, Headers ,方法等。它可以以各种方式提供:

27.5 基于过滤器的CORS支持

为了支持CORS和基于过滤器的安全框架(如 Spring Security ),或者支持其他不支持本机CORS的库,Spring Framework还提供了 CorsFilter 。而不是使用 @CrossOriginWebMvcConfigurer#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;
	}
}

您需要确保在其他过滤器之前订购 CorsFilter ,请参阅 this blog post ,了解如何相应地配置Spring Boot。

Updated at: 5 months ago
26.4.19. 测试Table of contentVII. Integration
Comment
You are not logged in.

There are no comments.