Spring MVC 允许您处理 CORS(跨域资源共享)。本节 介绍如何执行此操作。Spring中文文档

介绍

出于安全原因,浏览器禁止对当前源之外的资源进行 AJAX 调用。 例如,您可以将您的银行帐户放在一个选项卡中,而将 evil.com 放在另一个选项卡中。脚本 从 evil.com 应该无法使用您的银行 API 向您的银行 API 发出 AJAX 请求 凭据 - 例如从您的帐户中提取资金!Spring中文文档

跨域资源共享 (CORS) 是大多数浏览器实现的 W3C 规范,允许您指定 授权什么样的跨域请求,而不是使用安全性更低、安全性更低的请求 基于 IFRAME 或 JSONP 的强大解决方法。Spring中文文档

凭据请求

将 CORS 与带凭证的请求一起使用需要启用 。请注意 此选项与配置的域建立高度信任,并增加 通过公开敏感的用户特定信息来攻击 Web 应用程序的表面 例如 Cookie 和 CSRF 令牌。allowedCredentialsSpring中文文档

启用凭据也会影响配置的 CORS 通配符的处理方式:"*"Spring中文文档

  • 通配符在 中未授权,但 该属性可用于匹配一组动态原点。allowOriginsallowOriginPatternsSpring中文文档

  • 当设置为 或 时,通过复制相关的 CORS 预检请求中指定的标头和方法。allowedHeadersallowedMethodsAccess-Control-Allow-HeadersAccess-Control-Allow-MethodsSpring中文文档

  • 设置为打开时,将设置响应标头 添加到配置的标头列表或通配符。虽然 CORS 规范 不允许通配符 when 设置为 ,大多数浏览器都支持通配符,并且响应标头在 CORS 处理,因此通配符是当 无论属性的值如何,都指定。exposedHeadersAccess-Control-Expose-HeadersAccess-Control-Allow-CredentialstrueallowCredentialsSpring中文文档

虽然这种通配符配置可能很方便,但建议在可能的情况下进行配置 一组有限的值,以提供更高级别的安全性。
虽然这种通配符配置可能很方便,但建议在可能的情况下进行配置 一组有限的值,以提供更高级别的安全性。

加工

CORS 规范区分了印前检查、简单请求和实际请求。 要了解 CORS 的工作原理,您可以阅读本文,其中包括 许多其他,或查看规范了解更多详细信息。Spring中文文档

Spring MVC 实现提供对 CORS 的内置支持。成功后 将请求映射到处理程序,实现会检查 CORS 配置中的 给定请求和处理程序,并采取进一步的行动。处理印前检查请求 直接,而简单和实际的 CORS 请求被拦截、验证并具有 设置所需的 CORS 响应标头。HandlerMappingHandlerMappingSpring中文文档

为了启用跨域请求(即,标头存在且 与请求的主机不同),您需要有一些显式声明的 CORS 配置。如果未找到匹配的 CORS 配置,则预检请求为 拒绝。不会将 CORS 标头添加到简单和实际 CORS 请求的响应中 因此,浏览器会拒绝它们。OriginSpring中文文档

每个都可以使用基于 URL 模式的映射单独配置。在大多数情况下,应用程序 使用 MVC Java 配置或 XML 命名空间声明此类映射,结果 在传递到所有实例的单个全局映射中。HandlerMappingCorsConfigurationHandlerMappingSpring中文文档

您可以将全局 CORS 配置与更多级别组合在一起 细粒度的处理程序级 CORS 配置。例如,带注释的控制器可以使用 类级或方法级注释(其他处理程序可以实现)。HandlerMapping@CrossOriginCorsConfigurationSourceSpring中文文档

组合全局和本地配置的规则通常是累加的,例如, 所有全球和所有本地来源。对于只能有一个值的属性 接受,例如 并且,局部值将覆盖全局值。有关详细信息,请参阅 CorsConfiguration#combine(CorsConfiguration)。allowCredentialsmaxAgeSpring中文文档

若要从源代码中了解详细信息或进行高级自定义,请检查背后的代码:Spring中文文档

若要从源代码中了解详细信息或进行高级自定义,请检查背后的代码:Spring中文文档

@CrossOrigin

@CrossOrigin注释支持对带注释的控制器方法进行跨域请求, 如以下示例所示:Spring中文文档

@RestController
@RequestMapping("/account")
public class AccountController {

	@CrossOrigin
	@GetMapping("/{id}")
	public Account retrieve(@PathVariable Long id) {
		// ...
	}

	@DeleteMapping("/{id}")
	public void remove(@PathVariable Long id) {
		// ...
	}
}
@RestController
@RequestMapping("/account")
class AccountController {

	@CrossOrigin
	@GetMapping("/{id}")
	fun retrieve(@PathVariable id: Long): Account {
		// ...
	}

	@DeleteMapping("/{id}")
	fun remove(@PathVariable id: Long) {
		// ...
	}
}

默认情况下,允许:@CrossOriginSpring中文文档

allowCredentials默认情况下不启用,因为这会建立信任级别 公开敏感的用户特定信息(例如 Cookie 和 CSRF 令牌),以及 应仅在适当的情况下使用。启用后,必须 设置为一个或多个特定域(但不是特殊值)或 该属性可用于匹配一组动态原点。allowOrigins"*"allowOriginPatternsSpring中文文档

maxAge设置为 30 分钟。Spring中文文档

@CrossOrigin在类级别也受支持,并且由所有方法继承, 如以下示例所示:Spring中文文档

@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(origins = ["https://domain2.com"], maxAge = 3600)
@RestController
@RequestMapping("/account")
class AccountController {

	@GetMapping("/{id}")
	fun retrieve(@PathVariable id: Long): Account {
		// ...
	}

	@DeleteMapping("/{id}")
	fun remove(@PathVariable id: Long) {
		// ...
	}

您可以在类级别和方法级别使用 如以下示例所示:@CrossOriginSpring中文文档

@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) {
		// ...
	}
}
@CrossOrigin(maxAge = 3600)
@RestController
@RequestMapping("/account")
class AccountController {

	@CrossOrigin("https://domain2.com")
	@GetMapping("/{id}")
	fun retrieve(@PathVariable id: Long): Account {
		// ...
	}

	@DeleteMapping("/{id}")
	fun remove(@PathVariable id: Long) {
		// ...
	}
}

全局配置

除了细粒度的控制器方法级配置外,您可能还希望 还要定义一些全局 CORS 配置。您可以在任何 .但是,大多数应用程序都使用 MVC Java 配置或 MVC XML 命名空间来执行此操作。CorsConfigurationHandlerMappingSpring中文文档

默认情况下,全局配置启用以下功能:Spring中文文档

allowCredentials默认情况下不启用,因为这会建立信任级别 公开敏感的用户特定信息(例如 Cookie 和 CSRF 令牌),以及 应仅在适当的情况下使用。启用后,必须 设置为一个或多个特定域(但不是特殊值)或 该属性可用于匹配一组动态原点。allowOrigins"*"allowOriginPatternsSpring中文文档

maxAge设置为 30 分钟。Spring中文文档

Java 配置

若要在 MVC Java 配置中启用 CORS,可以使用回调, 如以下示例所示:CorsRegistrySpring中文文档

@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...
	}
}
@Configuration
@EnableWebMvc
class WebConfig : WebMvcConfigurer {

	override fun addCorsMappings(registry: CorsRegistry) {

		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 配置

若要在 XML 命名空间中启用 CORS,可以使用以下元素: 如以下示例所示:<mvc:cors>Spring中文文档

<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>

CORS过滤器

您可以通过内置的 CorsFilter 应用 CORS 支持。Spring中文文档

如果您尝试将 Spring Security 与 Spring Security 一起使用,请记住 Spring 安全性具有内置支持 CORS。CorsFilter

若要配置筛选器,请将 a 传递给其构造函数,作为 以下示例显示:CorsConfigurationSourceSpring中文文档

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);
val config = CorsConfiguration()

// Possibly...
// config.applyPermitDefaultValues()

config.allowCredentials = true
config.addAllowedOrigin("https://domain1.com")
config.addAllowedHeader("*")
config.addAllowedMethod("*")

val source = UrlBasedCorsConfigurationSource()
source.registerCorsConfiguration("/**", config)

val filter = CorsFilter(source)
如果您尝试将 Spring Security 与 Spring Security 一起使用,请记住 Spring 安全性具有内置支持 CORS。CorsFilter