

# 配置跨源资源共享 (CORS)
<a name="enabling-cors-examples"></a>

跨源资源共享 (CORS) 定义了在一个域中加载的客户端 Web 应用程序与另一个域中的资源交互的方式。借助 CORS 支持，您可以使用 Amazon S3 构建各种富客户端 Web 应用程序，并选择性地允许跨源访问您的 Amazon S3 资源。

本节将向您介绍如何使用 Amazon S3 控制台、Amazon S3 REST API 和 Amazon SDK 来启用 CORS。要将您的存储桶配置为允许跨源请求，您可以将 CORS 配置添加到存储桶中。CORS 配置是一个定义规则的文档，这些规则标识可访问您的存储桶的源、每个源支持的操作（HTTP 方法）以及其他操作特定的信息。在 S3 控制台中，CORS 配置必须是 JSON 文档。

有关 JSON 和 XML 中的 CORS 配置示例，请参阅 [CORS 配置的元素](ManageCorsUsing.md)。

## 使用 S3 控制台
<a name="add-cors-configuration"></a>

本节说明如何使用 Amazon S3 控制台向 S3 存储桶添加跨源资源共享（CORS）配置。

在存储桶上启用 CORS 时，访问控制列表（ACL）和其他访问权限策略仍适用。

**重要**  
在 S3 控制台中，CORS 配置必须是 JSON。有关 JSON 和 XML 中的 CORS 配置示例，请参阅 [CORS 配置的元素](ManageCorsUsing.md)。

**将 CORS 配置添加到 S3 存储桶**

1. 登录到 Amazon Web Services 管理控制台，然后通过以下网址打开 Amazon S3 控制台：[https://console.aws.amazon.com/s3/](https://console.amazonaws.cn/s3/)。

1. 在左侧导航窗格中，选择**通用存储桶**。

1. 在存储桶列表中，选择要为其创建存储桶策略的存储桶的名称。

1. 选择 **Permissions (权限)**。

1. 在 **Cross-origin resource sharing（CORS）（跨源资源共享（CORS））**部分中，请选择 **Edit（编辑）**。

1. 在 **CORS configuration editor (CORS 配置编辑器)** 文本框中，键入或复制并粘贴新的 CORS 配置，或者编辑现有配置。

   CORS 配置是一个 JSON 文件。您在编辑器中键入的文本必须是有效的 JSON。有关更多信息，请参阅 [CORS 配置的元素](ManageCorsUsing.md)。

1. 请选择**保存更改**。
**注意**  
Amazon S3 在 **CORS configuration editor（CORS 配置编辑器）**标题旁边显示存储桶的 Amazon Resource Name（ARN）。有关 ARN 的更多信息，请参阅《Amazon Web Services 一般参考》**中的 [Amazon 资源名称（ARN）和 Amazon 服务命名空间](https://docs.amazonaws.cn/general/latest/gr/aws-arns-and-namespaces.html)。

## 使用 Amazon 开发工具包
<a name="ManageCorsUsingSDK"></a>

您可以使用 Amazon SDK 管理存储桶的跨源资源共享（CORS）。有关 CORS 的更多信息，请参阅 [使用跨源资源共享 (CORS)](cors.md)。

 以下示例：
+ 创建 CORS 配置并对存储桶设置该配置
+ 通过添加规则来检索并修改配置
+ 向存储桶添加修改过的配置
+ 删除配置

------
#### [ Java ]

**Example**  

**Example**  
 有关如何创建和测试有效示例的说明，请参阅《适用于 Java 的 Amazon SDK 开发人员指南》中的[入门](https://docs.amazonaws.cn/sdk-for-java/v1/developer-guide/getting-started.html)。  

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.SdkClientException;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.BucketCrossOriginConfiguration;
import com.amazonaws.services.s3.model.CORSRule;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class CORS {

    public static void main(String[] args) throws IOException {
        Regions clientRegion = Regions.DEFAULT_REGION;
        String bucketName = "*** Bucket name ***";

        // Create two CORS rules.
        List<CORSRule.AllowedMethods> rule1AM = new ArrayList<CORSRule.AllowedMethods>();
        rule1AM.add(CORSRule.AllowedMethods.PUT);
        rule1AM.add(CORSRule.AllowedMethods.POST);
        rule1AM.add(CORSRule.AllowedMethods.DELETE);
        CORSRule rule1 = new CORSRule().withId("CORSRule1").withAllowedMethods(rule1AM)
                .withAllowedOrigins(Arrays.asList("http://*.example.com"));

        List<CORSRule.AllowedMethods> rule2AM = new ArrayList<CORSRule.AllowedMethods>();
        rule2AM.add(CORSRule.AllowedMethods.GET);
        CORSRule rule2 = new CORSRule().withId("CORSRule2").withAllowedMethods(rule2AM)
                .withAllowedOrigins(Arrays.asList("*")).withMaxAgeSeconds(3000)
                .withExposedHeaders(Arrays.asList("x-amz-server-side-encryption"));

        List<CORSRule> rules = new ArrayList<CORSRule>();
        rules.add(rule1);
        rules.add(rule2);

        // Add the rules to a new CORS configuration.
        BucketCrossOriginConfiguration configuration = new BucketCrossOriginConfiguration();
        configuration.setRules(rules);

        try {
            AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
                    .withCredentials(new ProfileCredentialsProvider())
                    .withRegion(clientRegion)
                    .build();

            // Add the configuration to the bucket.
            s3Client.setBucketCrossOriginConfiguration(bucketName, configuration);

            // Retrieve and display the configuration.
            configuration = s3Client.getBucketCrossOriginConfiguration(bucketName);
            printCORSConfiguration(configuration);

            // Add another new rule.
            List<CORSRule.AllowedMethods> rule3AM = new ArrayList<CORSRule.AllowedMethods>();
            rule3AM.add(CORSRule.AllowedMethods.HEAD);
            CORSRule rule3 = new CORSRule().withId("CORSRule3").withAllowedMethods(rule3AM)
                    .withAllowedOrigins(Arrays.asList("http://www.example.com"));

            rules = configuration.getRules();
            rules.add(rule3);
            configuration.setRules(rules);
            s3Client.setBucketCrossOriginConfiguration(bucketName, configuration);

            // Verify that the new rule was added by checking the number of rules in the
            // configuration.
            configuration = s3Client.getBucketCrossOriginConfiguration(bucketName);
            System.out.println("Expected # of rules = 3, found " + configuration.getRules().size());

            // Delete the configuration.
            s3Client.deleteBucketCrossOriginConfiguration(bucketName);
            System.out.println("Removed CORS configuration.");

            // Retrieve and display the configuration to verify that it was
            // successfully deleted.
            configuration = s3Client.getBucketCrossOriginConfiguration(bucketName);
            printCORSConfiguration(configuration);
        } catch (AmazonServiceException e) {
            // The call was transmitted successfully, but Amazon S3 couldn't process
            // it, so it returned an error response.
            e.printStackTrace();
        } catch (SdkClientException e) {
            // Amazon S3 couldn't be contacted for a response, or the client
            // couldn't parse the response from Amazon S3.
            e.printStackTrace();
        }
    }

    private static void printCORSConfiguration(BucketCrossOriginConfiguration configuration) {
        if (configuration == null) {
            System.out.println("Configuration is null.");
        } else {
            System.out.println("Configuration has " + configuration.getRules().size() + " rules\n");

            for (CORSRule rule : configuration.getRules()) {
                System.out.println("Rule ID: " + rule.getId());
                System.out.println("MaxAgeSeconds: " + rule.getMaxAgeSeconds());
                System.out.println("AllowedMethod: " + rule.getAllowedMethods());
                System.out.println("AllowedOrigins: " + rule.getAllowedOrigins());
                System.out.println("AllowedHeaders: " + rule.getAllowedHeaders());
                System.out.println("ExposeHeader: " + rule.getExposedHeaders());
                System.out.println();
            }
        }
    }
}
```

------
#### [ .NET ]

**Example**  
有关设置和运行代码示例的信息，请参阅《适用于 .NET 的 Amazon SDK 开发人员指南》**中的[适用于 .NET 的 Amazon SDK 入门](https://docs.amazonaws.cn/sdk-for-net/latest/developer-guide/net-dg-setup.html)。  

```
using Amazon;
using Amazon.S3;
using Amazon.S3.Model;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Amazon.DocSamples.S3
{
    class CORSTest
    {
        private const string bucketName = "*** bucket name ***";
        // Specify your bucket region (an example region is shown).
        private static readonly RegionEndpoint bucketRegion = RegionEndpoint.USWest2; 
        private static IAmazonS3 s3Client;

        public static void Main()
        {
            s3Client = new AmazonS3Client(bucketRegion);
            CORSConfigTestAsync().Wait();
        }
        private static async Task CORSConfigTestAsync()
        {
            try
            {
                // Create a new configuration request and add two rules    
                CORSConfiguration configuration = new CORSConfiguration
                {
                    Rules = new System.Collections.Generic.List<CORSRule>
                        {
                          new CORSRule
                          {
                            Id = "CORSRule1",
                            AllowedMethods = new List<string> {"PUT", "POST", "DELETE"},
                            AllowedOrigins = new List<string> {"http://*.example.com"}
                          },
                          new CORSRule
                          {
                            Id = "CORSRule2",
                            AllowedMethods = new List<string> {"GET"},
                            AllowedOrigins = new List<string> {"*"},
                            MaxAgeSeconds = 3000,
                            ExposeHeaders = new List<string> {"x-amz-server-side-encryption"}
                          }
                        }
                };

                // Add the configuration to the bucket. 
                await PutCORSConfigurationAsync(configuration);

                // Retrieve an existing configuration. 
                configuration = await RetrieveCORSConfigurationAsync();

                // Add a new rule.
                configuration.Rules.Add(new CORSRule
                {
                    Id = "CORSRule3",
                    AllowedMethods = new List<string> { "HEAD" },
                    AllowedOrigins = new List<string> { "http://www.example.com" }
                });

                // Add the configuration to the bucket. 
                await PutCORSConfigurationAsync(configuration);

                // Verify that there are now three rules.
                configuration = await RetrieveCORSConfigurationAsync();
                Console.WriteLine();
                Console.WriteLine("Expected # of rulest=3; found:{0}", configuration.Rules.Count);
                Console.WriteLine();
                Console.WriteLine("Pause before configuration delete. To continue, click Enter...");
                Console.ReadKey();

                // Delete the configuration.
                await DeleteCORSConfigurationAsync();

                // Retrieve a nonexistent configuration.
                configuration = await RetrieveCORSConfigurationAsync();
            }
            catch (AmazonS3Exception e)
            {
                Console.WriteLine("Error encountered on server. Message:'{0}' when writing an object", e.Message);
            }
            catch (Exception e)
            {
                Console.WriteLine("Unknown encountered on server. Message:'{0}' when writing an object", e.Message);
            }
        }

        static async Task PutCORSConfigurationAsync(CORSConfiguration configuration)
        {

            PutCORSConfigurationRequest request = new PutCORSConfigurationRequest
            {
                BucketName = bucketName,
                Configuration = configuration
            };

            var response = await s3Client.PutCORSConfigurationAsync(request);
        }

        static async Task<CORSConfiguration> RetrieveCORSConfigurationAsync()
        {
            GetCORSConfigurationRequest request = new GetCORSConfigurationRequest
            {
                BucketName = bucketName

            };
            var response = await s3Client.GetCORSConfigurationAsync(request);
            var configuration = response.Configuration;
            PrintCORSRules(configuration);
            return configuration;
        }

        static async Task DeleteCORSConfigurationAsync()
        {
            DeleteCORSConfigurationRequest request = new DeleteCORSConfigurationRequest
            {
                BucketName = bucketName
            };
            await s3Client.DeleteCORSConfigurationAsync(request);
        }

        static void PrintCORSRules(CORSConfiguration configuration)
        {
            Console.WriteLine();

            if (configuration == null)
            {
                Console.WriteLine("\nConfiguration is null");
                return;
            }

            Console.WriteLine("Configuration has {0} rules:", configuration.Rules.Count);
            foreach (CORSRule rule in configuration.Rules)
            {
                Console.WriteLine("Rule ID: {0}", rule.Id);
                Console.WriteLine("MaxAgeSeconds: {0}", rule.MaxAgeSeconds);
                Console.WriteLine("AllowedMethod: {0}", string.Join(", ", rule.AllowedMethods.ToArray()));
                Console.WriteLine("AllowedOrigins: {0}", string.Join(", ", rule.AllowedOrigins.ToArray()));
                Console.WriteLine("AllowedHeaders: {0}", string.Join(", ", rule.AllowedHeaders.ToArray()));
                Console.WriteLine("ExposeHeader: {0}", string.Join(", ", rule.ExposeHeaders.ToArray()));
            }
        }
    }
}
```

------

## 使用 REST API
<a name="EnableCorsUsingREST"></a>

要对存储桶设置 CORS 配置，您可以使用 Amazon Web Services 管理控制台。如果您的应用程序需要它，您也可以直接发送 REST 请求。*Amazon Simple Storage Service API 参考*的下面几节描述了与 CORS 配置相关的 REST API 操作：
+ [PutBucketCors](https://docs.amazonaws.cn/AmazonS3/latest/API/RESTBucketPUTcors.html)
+ [GetBucketCors](https://docs.amazonaws.cn/AmazonS3/latest/API/RESTBucketGETcors.html)
+ [DeleteBucketCors](https://docs.amazonaws.cn/AmazonS3/latest/API/RESTBucketDELETEcors.html)
+ [OPTIONS object](https://docs.amazonaws.cn/AmazonS3/latest/API/RESTOPTIONSobject.html)