

# CORS 问题排查
<a name="cors-troubleshooting"></a>

以下主题有助于排查与 S3 相关的一些常见 CORS 问题。

**Topics**
+ [403 禁止错误 - 未为此存储桶启用 CORS](#cors-not-enabled)
+ [403 禁止错误 - 不支持此 CORS 请求](#cors-not-enabled)
+ [在 CORS 响应中找不到标头](#Headers-not-found)
+ [有关 S3 代理集成的 CORS 的注意事项](#cors-in-proxy)

## 403 禁止错误：未为此存储桶启用 CORS
<a name="cors-not-enabled"></a>

当跨源请求发送到 Amazon S3 但未在 S3 存储桶上配置 CORS 时，会发生以下 `403 Forbidden` 错误。

 错误：HTTP/1.1 403 禁止 CORS 响应：未为此存储桶启用 CORS。

CORS 配置是一个包含规则的文档或策略，这些规则标识可访问您的存储桶的源、每个源将支持的操作（HTTP 方法）以及其它操作特定的信息。请参阅如何使用 Amazon S3 控制台、AWS SDK 和 REST API 在 S3 上[配置 CORS](https://docs.aws.amazon.com/AmazonS3/latest/userguide/enabling-cors-examples.html)。有关 CORS 的更多信息以及 CORS 配置示例，请参阅 [CORS 的元素](https://docs.aws.amazon.com/AmazonS3/latest/userguide/ManageCorsUsing.html#cors-example-1)。

## 403 禁止错误：不支持此 CORS 请求
<a name="cors-not-enabled"></a>

当 CORS 配置中的 CORS 规则与请求中的数据不匹配时，会收到以下 `403 Forbidden` 错误。

错误：HTTP/1.1 403 禁止 CORS 响应：不支持此 CORS 请求。

因此，出现此 `403 Forbidden` 错误的原因可能有多种：
+ 不支持源。
+ 不支持方法。
+ 不支持请求的标头。

对于 Amazon S3 收到的每个请求，CORS 配置中必须具有与请求中的数据匹配的 CORS 规则。

### 不支持源
<a name="Origin-not-allowed"></a>

 向存储桶发出的 CORS 请求中的 `Origin` 标头必须与 CORS 配置的 `AllowedOrigins` 元素中的源相匹配。`AllowedOrigins` 元素中的通配符 (`"*"`) 将匹配所有 HTTP 方法。有关如何更新 `AllowedOrigins` 元素的更多信息，请参阅[配置跨源资源共享（CORS）](https://docs.aws.amazon.com/AmazonS3/latest/userguide/enabling-cors-examples.html)。

 例如，如果 `AllowedOrigins` 元素中仅包含 `http://www.example1.com` 域，则从 `http://www.example2.com` 域发送的 CORS 请求将收到 `403 Forbidden` 错误。

以下示例显示 CORS 配置的一部分，它在 `AllowedOrigins` 元素中包含 `http://www.example1.com` 域。

```
"AllowedOrigins":[
   "http://www.example1.com"
]
```

要使从 `http://www.example2.com` 域发送的 CORS 请求获得成功，应将 `http://www.example2.com` 域包含在 CORS 配置的 `AllowedOrigins` 元素中。

```
"AllowedOrigins":[
   "http://www.example1.com"
   "http://www.example2.com"
]
```

### 不支持方法
<a name="Methods-not-allowed"></a>

 在向存储桶发出的 CORS 请求的 `Access-Control-Request-Method` 中指定的 HTTP 方法，必须与在 CORS 配置的 `AllowedMethods` 元素中列出的一个或多个方法相匹配。`AllowedMethods` 中的通配符 (`"*"`) 将匹配所有 HTTP 方法。有关如何更新 `AllowedOrigins` 元素的更多信息，请参阅[配置跨源资源共享（CORS）](https://docs.aws.amazon.com/AmazonS3/latest/userguide/enabling-cors-examples.html)。

在 CORS 配置中，您可以在 `AllowedMethods` 元素中指定以下方法：
+ `GET`
+ `PUT`
+ `POST`
+ `DELETE`
+ `HEAD`

以下示例显示 CORS 配置的一部分，该配置在 `AllowedMethods` 元素中包含 `GET` 方法。只有包含 `GET` 方法的请求才会获得成功。

```
"AllowedMethods":[
   "GET"
]
```

 如果在 CORS 请求中使用了 HTTP 方法（例如 `PUT`），或者该方法包含在对存储桶的预检 CORS 请求中但不存在于 CORS 配置中，则该请求将导致 `403 Forbidden` 错误。要支持此 CORS 请求或 CORS 预检请求，必须将 `PUT` 方法添加到 CORS 配置中。

```
"AllowedMethods":[
   "GET"
   "PUT"
]
```

### 不支持请求的标头
<a name="Headers-not-allowed"></a>

 预检请求的 `Access-Control-Request-Headers` 标头中列出的标头必须与 CORS 配置的 `AllowedHeaders` 元素中的标头相匹配。有关可以在对 Amazon S3 的请求中使用的常见标头的列表，请参阅 [Common Request Headers](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTCommonRequestHeaders.html)。有关如何更新 `AllowedHeaders` 元素的更多信息，请参阅[配置跨源资源共享（CORS）](https://docs.aws.amazon.com/AmazonS3/latest/userguide/enabling-cors-examples.html)。

以下示例显示 CORS 配置的一部分，该配置在 `AllowedHeaders` 元素中包含 `Authorization` 标头。只有对 `Authorization` 标头的请求才会获得成功。

```
"AllowedHeaders":  [
    "Authorization"
]
```

 如果 CORS 请求中包含标头（例如 `Content-MD5`），但该标头不存在于 CORS 配置中，则该请求将导致 `403 Forbidden` 错误。要支持此 CORS 请求，必须将 `Content-MD5` 标头添加到 CORS 配置中。如果您要在 CORS 请求中同时将 `Authorization` 和 `Content-MD5` 标头传递到存储桶，请确认这两个标头都包含在 CORS 配置的 `AllowedHeaders` 元素中。

```
"AllowedHeaders":  [
    "Authorization"
    "Content-MD5"
]
```

## 在 CORS 响应中找不到标头
<a name="Headers-not-found"></a>

 CORS 配置中的 `ExposeHeaders` 元素确定了您希望在浏览器中运行的脚本和应用程序可以访问哪些响应标头，以便响应 CORS 请求。

如果存储在 S3 存储桶中的对象具有用户定义的元数据（例如 `x-amz-meta-custom-header`）以及响应数据，则此自定义标头可能包含您要从客户端 JavaScript 代码访问的其它元数据或信息。但出于安全考虑，默认情况下，浏览器会阻止访问自定义标头。要支持客户端 JavaScript 访问自定义标头，需要在 CORS 配置中包含该标头。

 在下面的示例中，`x-amz-meta-custom-header1` 标头包含在 `ExposeHeaders` 元素中。`x-amz-meta-custom-header2` 未包含在 `ExposeHeaders` 元素中，并且 CORS 配置中也缺少此标头。在响应中，仅返回 `ExposeHeaders` 元素中包含的值。如果请求在 `Access-Control-Expose-Headers` 标头中包含了 `x-amz-meta-custom-header2` 标头，则响应仍会返回 `200 OK`。但是，只有允许的标头（例如 `x-amz-meta-custom-header`）才会返回并显示在响应中。

```
"ExposeHeaders":  [
    "x-amz-meta-custom-header1"
]
```

 为确保所有标头都出现在响应中，请将所有允许的标头添加到 CORS 配置中的 `ExposeHeaders` 元素，如下所示。

```
"ExposeHeaders":  [
    "x-amz-meta-custom-header1",
    "x-amz-meta-custom-header2"
]
```

## 有关 S3 代理集成的 CORS 的注意事项
<a name="cors-in-proxy"></a>

如果您遇到错误且已经检查了 S3 存储桶上的 CORS 配置，并且跨源请求已发送到 AWS CloudFront 等代理，请尝试以下操作：
+ 将设置配置为支持 HTTP 请求使用 `OPTIONS` 方法。
+ 将代理配置为转发以下标头：`Origin`、`Access-Control-Request-Headers` 和 `Access-Control-Request-Method`。
+ 将代理设置配置为在其缓存密钥中包含 origin 标头。这一点很重要，这是因为：如果缓存代理在其缓存密钥中不包含 origin 标头，则它们提供的缓存响应可能对于不同的源不包含适当的 CORS 标头。

一些代理为 CORS 请求提供预定义的功能。例如，在 CloudFront 中，您可以配置一个策略，该策略包括的标头 

 可在源为 Amazon S3 存储桶时启用跨源资源共享（CORS）请求。

 此策略包含以下设置：
+ 源请求中包含的标头：

   `Origin`

   `Access-Control-Request-Headers`

   `Access-Control-Request-Method`
+ 源请求中包含的 Cookie：无
+ 源请求中包含的查询字符串：无

有关更多信息，请参阅《CloudFront 开发人员指南》**中的[使用策略来控制源请求](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/controlling-origin-requests.htm)和[使用托管式源请求策略](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-managed-origin-request-policies.html#managed-origin-request-policy-cors-s3)。