# 1.6 CORS

Spring MVC使您可以处理CORS（跨域资源共享）。本节介绍如何执行此操作。

## 1.6.1 介绍

出于安全原因，浏览器禁止AJAX调用当前来源以外的资源。例如，您可以将您的银行帐户放在一个标签中，将evil.com放在另一个标签中。来自evil.com的脚本不能使用您的凭据向您的银行API发出AJAX请求，例如从您的帐户中提取资金！

跨域资源共享（CORS）是大多数浏览器实施的W3C规范，可让您指定授权哪种类型的跨域请求，而不是使用基于IFRAME或JSONP的安全性较低且功能较弱的变通办法。

## 1.6.2 Processing

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

## 1.6.3 @CrossOrigin

@CrossOrigin批注启用带注解的控制器方法上的跨域请求，如以下示例所示：

```java
@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在类级别上也受支持，并且被所有方法继承，如以下示例所示：

```java
@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，如以下示例所示：

```java
@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) {
        // ...
    }
}
```

## 1.6.4 Global Configuration

除了细粒度的控制器方法级别配置外，您可能还想定义一些全局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回调，如以下示例所示：

```java
@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>元素，如以下示例所示：

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

## 1.6.5 CORS Filter

您可以通过内置的CorsFilter应用CORS支持。

> 如果您尝试将CorsFilter与Spring Security一起使用，请记住Spring Security内置了对CORS的支持。

要配置过滤器，请将CorsConfigurationSource传递给其构造函数，如以下示例所示：

```java
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);
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.flydean.com/spring-framework-documentation5/webservlet/1.spring-web-mvc/1.6cors.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
