目录
AWS Identity and Access Management
文献参考:
Amazon S3(Amazon Simple Storage Service),是互联网存储解决方案。该服务旨在降低开发人员进行网络规模级计算的难度。
Amazon S3 提供了一个简单的Web服务接口,可用于随时在Web上的任何位置存储和检索任何数量的数据。
Amazon S3 特意内置了着重于简易性和稳健性的最小功能集。以下是 Amazon S3 服务的一些优势:
- 创建存储桶 – 创建和命名存储数据的存储桶。存储桶是 Amazon S3 中用于数据存储的基础容器。
-
在存储桶中存储数据 – 在存储桶中存储无限量的数据。可将所需数量的对象上传到 Amazon S3 存储桶。每个对象可包含最多 5TB的数据。使用开发人员分配的唯一键值存储和检索每个对象。
- 下载数据 – 下载您的数据或允许其他人下载。随时下载您的数据或允许其他人执行相同的操作。
- 权限 - 对于要在您的 Amazon S3 存储桶中上传或下载数据的其他人员,您可授予其访问权限或拒绝其访问。将上传和下载的许可授予3种类型的用户。身份验证机制可帮助确保数据安全,以防未授权访问
- 标准接口 – 使用标准的REST接口(SOAP接口已弃用),它们可与任何 Internet 开发工具包搭配使用
存储桶
每个对象都储存在一个存储桶中。例如,如果名为 photos/puppy.jpg
的对象存储在 johnsmith
存储桶中,则可使用 URL http://johnsmith.s3.amazonaws.com/photos/puppy.jpg
对该对象进行寻址
存储桶有以下几种用途:组织最高等级的 Amazon S3 命名空间、识别负责存储和数据传输费用的账户、在访问控制中发挥作用以及用作使用率报告的汇总单位。
您可以配置存储桶,以便在特定区域进行创建。有关详细信息,请参阅存储桶和区域。您也可以配置存储桶,以便在每次向它添加对象时,Amazon S3 都会生成一个唯一的版本 ID 并将其分配给对象。有关详细信息,请参阅版本控制。
默认,可在每个 AWS 账户中创建100个存储桶。如果需要更多存,可通过提交服务限额提升来调高存储桶限制
创建存储桶时,需提供名称及要在其中创建存储桶的AWS区域(美国东部(弗吉尼亚北部)是默认区域,如果通过指定美国东部区域创建客户端,则客户端将使用s3.amazonaws.com节点与S3通信)
创建存储桶后,无法更改其区域
一个存储桶中可存储任意数量的对象
可用AWS账户根凭证创建存储桶并执行其他S3操作。但建议不要用AWS账户的根凭证发出请求 (如创建存储桶)。而是创建一个 IAM 用户,并向该用户授予完全访问权限 (用户默认没有任何权限)。我们将这些用户称管理员用户。可用管理员用户凭证而不是您账户的根凭证来与AWS交互和执行任务,例如创建存储桶,创建用户和授予他们权限
创建资源的 AWS 账户拥有该资源。例如,如果您在您的AWS账户中创建一个IAM用户并向该用户授予创建存储桶的权限,则该用户可创建存储桶。但不拥有;用户所属的AWS账户拥有存储桶。用户需资源拥有者提供其他权限来执行任何其他存储桶操作
S3支持虚拟托管和路径类型URL访问存储桶
- 虚拟托管URL中,存储桶名称是URL域名的一部分,e.g.,
http://
如果向bucket
.s3.amazonaws.com,http://bucket
.s3-aws-region
.amazonaws.com.http://
终端节点发出请求,则DNS有足够信息将请求直接路由到存储桶所位于的区域bucket
.s3.amazonaws.com - 路径类型URL中,存储桶名称不包含在域中 (除非使用特定于区域的终端节点),e.g.,美国东部区域终端节点
http://s3.amazonaws.com/
特定于区域的终端节点bucket,
http://s3-
aws-region
.amazonaws.com/bucket
存储桶所有权不可转让;但如果存储桶为空,可以删除。删除后,该名称可供重用,但是出于各种原因,您可能无法重用。e.g.,其他账户可能使用该名称创建存储桶。另请注意,该名称可能需过一段时间才能重用。因此,如果您想要使用相同的存储桶名称,请不要删除
S3的高可用性设计主要关注获取、放置、列出和删除操作。由于存储桶操作针对集中的全球资源空间工作,因此不适合在应用程序的高可用性代码路径上创建或删除存储桶。最好是在单独的初始化或设置不常运行的例程时创建或删除存储桶
以下是S3存储桶命名规则
- 在S3中的所有现有存储桶名称中必须唯一
- 必须符合DNS命名约定
- 名称长度必须为至少3个字符,且不能超过 63 个字符
- 名称不能包含大写字符或下划线
- 名称必须以小写字母或数字开头
- 名称必须是一系列的一个或多个标签。相邻标签通过单个句点 (.) 分隔。名称可以包含小写字母、数字和连字符。每个标签都必须以小写字母或数字开头和结尾
- 名称不得采用IP地址格式
- 当通过安全套接字 (SSL) 使用虚拟托管式存储桶时,SSL通配符证书仅匹配不包含句点的存储桶。要解决此问题,请使用 HTTP或编写自己的证书验证逻辑
Java创建存储桶
import java.io.IOException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.SdkClientException;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.CreateBucketRequest;
import com.amazonaws.services.s3.model.GetBucketLocationRequest;
public class CreateBucket {
public static void main(String[] args) throws IOException {
String clientRegion = "*** Client region ***";
String bucketName = "*** Bucket name ***";
try {
AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
.withCredentials(new ProfileCredentialsProvider())
.withRegion(clientRegion)
.build();
if (!s3Client.doesBucketExistV2(bucketName)) {
// Because the CreateBucketRequest object doesn't specify a region, the
// bucket is created in the region specified in the client.
s3Client.createBucket(new CreateBucketRequest(bucketName));
// Verify that the bucket was created by retrieving it and checking its location.
String bucketLocation = s3Client.getBucketLocation(new GetBucketLocationRequest(bucketName));
System.out.println("Bucket location: " + bucketLocation);
}
}
catch(AmazonServiceException e) {
// The call was transmitted successfully, but Amazon S3 couldn't process
// it and 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();
}
}
}
CLI删除存储桶
$ aws s3 rb s3://bucket-name --force
Java删除存储桶
import java.util.Iterator;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.SdkClientException;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.ListVersionsRequest;
import com.amazonaws.services.s3.model.ObjectListing;
import com.amazonaws.services.s3.model.S3ObjectSummary;
import com.amazonaws.services.s3.model.S3VersionSummary;
import com.amazonaws.services.s3.model.VersionListing;
public class DeleteBucket {
public static void main(String[] args) {
String clientRegion = "*** Client region ***";
String bucketName = "*** Bucket name ***";
try {
AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
.withCredentials(new ProfileCredentialsProvider())
.withRegion(clientRegion)
.build();
// Delete all objects from the bucket. This is sufficient
// for unversioned buckets. For versioned buckets, when you attempt to delete objects, Amazon S3 inserts
// delete markers for all objects, but doesn't delete the object versions.
// To delete objects from versioned buckets, delete all of the object versions before deleting
// the bucket (see below for an example).
ObjectListing objectListing = s3Client.listObjects(bucketName);
while (true) {
Iterator<S3ObjectSummary> objIter = objectListing.getObjectSummaries().iterator();
while (objIter.hasNext()) {
s3Client.deleteObject(bucketName, objIter.next().getKey());
}
// If the bucket contains many objects, the listObjects() call
// might not return all of the objects in the first listing. Check to
// see whether the listing was truncated. If so, retrieve the next page of objects
// and delete them.
if (objectListing.isTruncated()) {
objectListing = s3Client.listNextBatchOfObjects(objectListing);
} else {
break;
}
}
// Delete all object versions (required for versioned buckets).
VersionListing versionList = s3Client.listVersions(new ListVersionsRequest().withBucketName(bucketName));
while (true) {
Iterator<S3VersionSummary> versionIter = versionList.getVersionSummaries().iterator();
while (versionIter.hasNext()) {
S3VersionSummary vs = versionIter.next();
s3Client.deleteVersion(bucketName, vs.getKey(), vs.getVersionId());
}
if (versionList.isTruncated()) {
versionList = s3Client.listNextBatchOfVersions(versionList);
} else {
break;
}
}
// After all objects and object versions are deleted, delete the bucket.
s3Client.deleteBucket(bucketName);
}
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();
}
}
}
可配置存储桶的生命周期以使对象过期,S3随后将删除过期对象。可添加生命周期配置规则,以使所有或部分带特定键名称前缀的对象过期。e.g.,要删除存储桶中所有对象,可将生命周期规则设置为使对象在创建一天后过期。在S3删除所有对象后,可删除或保留存储桶.(未启用版本控制的存储桶,可直接删除所有对象,然后删除存储桶。启用了版本控制的存储桶,必须先删除所有对象版本,然后再删除存储桶)
CLI清空存储桶
$ aws s3 rm s3://bucket-name/doc --recursive
S3默认加密提供了一种方法来设置S3存储桶的默认加密行为。可对存储桶设置默认加密,以便在存储桶中存储所有对象时对这些对象进行加密。这些对象使用S3托管密钥 (SSE-S3) 或 AWS KMS托管密钥 (SSE-KMS) 通过服务器端进行加密。在使用服务器端加密时,S3在将对象保存到其数据中心的磁盘前对其加密,在下载对象时对其解密。对S3存储桶使用默认加密不会产生新的费用。请求配置默认加密功能会产生标准S3请求费用
为存储桶启用默认加密后,将会应用以下加密行为
- 启用默认加密后上传对象时:如果
PUT
请求标头不包含加密信息,则S3将使用默认加密设置来加密对象;如果PUT
请求标头包含加密信息,则S3将使用PUT
请求中的加密信息加密对象,然后再将对象存储。如果PUT
成功,则响应HTTP/1.1 200 OK
,并且响应标头中包含加密信息 - 如果将SSE-KMS选项用于默认加密配置,则您将受到AWS KMS的RPS(每秒请求数)限制
Java管理存储桶的网站配置(要将网站配置添加到存储桶,请提供存储桶名称和网站配置。网站配置必须包含索引文档,且可包含可选的错误文档。这些文档必须已存在于存储桶)
import java.io.IOException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.SdkClientException;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.BucketWebsiteConfiguration;
public class WebsiteConfiguration {
public static void main(String[] args) throws IOException {
String clientRegion = "*** Client region ***";
String bucketName = "*** Bucket name ***";
String indexDocName = "*** Index document name ***";
String errorDocName = "*** Error document name ***";
try {
AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
.withRegion(clientRegion)
.withCredentials(new ProfileCredentialsProvider())
.build();
// Print the existing website configuration, if it exists.
printWebsiteConfig(s3Client, bucketName);
// Set the new website configuration.
s3Client.setBucketWebsiteConfiguration(bucketName, new BucketWebsiteConfiguration(indexDocName, errorDocName));
// Verify that the configuration was set properly by printing it.
printWebsiteConfig(s3Client, bucketName);
// Delete the website configuration.
s3Client.deleteBucketWebsiteConfiguration(bucketName);
// Verify that the website configuration was deleted by printing it.
printWebsiteConfig(s3Client, bucketName);
}
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 printWebsiteConfig(AmazonS3 s3Client, String bucketName) {
System.out.println("Website configuration: ");
BucketWebsiteConfiguration bucketWebsiteConfig = s3Client.getBucketWebsiteConfiguration(bucketName);
if (bucketWebsiteConfig == null) {
System.out.println("No website config.");
} else {
System.out.println("Index doc: " + bucketWebsiteConfig.getIndexDocumentSuffix());
System.out.println("Error doc: " + bucketWebsiteConfig.getErrorDocument());
}
}
}
S3 Transfer Acceleration 可在客户与S3存储桶间实现快速、轻松、安全的远距离文件传输。Transfer Acceleration利用Amazon CloudFront的全球分布式边缘站点。当数据到达某个边缘站点时,会被经过优化的网络路径路由至S3
对象
对象是 Amazon S3 中存储的基本实体。对象由对象数据和元数据组成。数据部分对S3不透明。元数据是一组描述对象的名称-值对。其中包括一些默认元数据 (如上次修改日期) 和标准 HTTP 元数据 (如 Content-Type)。您还可在存储对象时指定自定义元数据。
在存储桶中,对象将由键 (名称) 和版本 ID 进行唯一标识
S3数据模型是一种扁平结构。不存在子存储桶或子文件夹层次结构;但可用键名称前缀和分隔符推断逻辑层次结构
键名称中的以下字符可能需要进行代码处理,且可能需要以16进制形式在URL中编码或引用。其中部分字符是不可打印的字符,浏览器可能无法处理,这也需特殊处理
表示和的符号 (“&”) | 美元 (“$”) | ASCII 字符范围 00–1F 十六进制 (0–31 十进制) 和 7F (127 十进制) |
“At”符号 (“@”) | 等于 (“=”) | 分号 (“;”) |
冒号 (“:”) | 加号 (“+”) | 空格 – 大量连续空格可能会在某些使用情形中丢失 (特别是多个空格) |
逗号 (“,”) | 问号 (“?”) |
避免在键名称中使用以下字符,因为这些字符需进行大量的特殊处理,才能在所有应用程序间保持一致性
反斜杠 ("\") | 左大括号 (“{”) | 不可打印的 ASCII 字符 (128–255 十进制字符) |
插入符号 (“^”) | 右大括号 (“}”) | 百分比字符 (“%”) |
重音符/反勾号 (“`”) | 右方括号 (“]”) | 引号 |
“大于”符号 (“>”) | 左方括号 (“[”) | 波浪字符 (“~”) |
“小于”符号 (“<”) | “井号”字符 (“#”) | 竖线 (“|”) |
S3中的每个对象都有与之关联的存储类别。e.g.,如果列出存储桶中的所有对象,则控制台会在列表中显示所有对象的存储类别
对于性能敏感的使用案例 (需ms级访问的用例) 和经常访问的数据,S3提供以下存储类
- STANDARD – 默认。如果上传对象时未指定存储类,S3会分配STANDARD
- REDUCED_REDUNDANCY – 低冗余存储 (RRS) 存储类设计用于可使用低于STANDARD存储类的冗余级别存储的非关键性可再生数据(建议不要使用此存储类。STANDARD存储类更经济高效.为实现持久性,RRS 对象的平均每年对象损失率为 0.01%。 如果RRS对象丢失,则在对该对象发出请求时,S3会返回405错误)
- STANDARD_IA和ONEZONE_IA存储类用于长时间运行且不经常访问的数据。(IA表示不经常访问)STANDARD_IA和ONEZONE_IA对象可用于ms级访问 (类似STANDARD)。S3会收取这些对象的检索费,因此,它们最适合不经常访问的数据.(STANDARD_IA和 ONEZONE_IA适用于计划存储至少30天且大小超过128KB的对象。如果对象小于128 KB,S3会收取128KB 的费用。如果在30天的最短使用期限前删除,则需支付30天的费用)
- STANDARD_IA – S3 跨多个地理位置独立的可用区存储冗余对象数据 (类似STANDARD)。STANDARD_IA对象可在出现可用区丢失时复原。此存储类可提供比ONEZONE_IA更好的可用性、持久性和弹性
- ONEZONE_IA – S3只在一个可用区存储对象数据,因此比STANDARD_IA便宜。但数据无法灵活地应对由于地震和洪灾造成可用区物理丢失的情况。ONEZONE_IA也具有持久性,但可用性和弹性较差
GLACIER
存储类适用于在不常访问数据的位置对数据存档。存档对象不可用于实时访问。必须先还原对象,才可访问。此存储类提供与STANDARD相同的持久性和弹性(如果选择Glacier,S3将使用低成本Glacier服务来存储对象。尽管对象存储在Glacier,它们仍是S3对象,需在S3中管理;且无法直接通过Glacier访问)(无法在创建对象时指定GLACIER存储类别。创建GLACIER对象时先用STANDARD、RRS、STANDARD_IA或ONEZONE_IA作为存储类别来上传这些对象。然后,使用生命周期管理将这些对象转换为GLACIER存储类别)
下表总结了每个存储类别提供的持久性和可用性
存储类别 | 持久性 (设计目标) | 可用性 (设计目标) | 其他考虑因素 |
---|---|---|---|
STANDARD | 99.999999999% | 99.99% | 无 |
STANDARD_IA | 99.999999999% | 99.9% | STANDARD_IA 对象会收取检索费用。此类最适合不经常访问的数据 |
ONEZONE_IA | 99.999999999% | 99.5% | 无法灵活地应对可用区丢失的情况 |
GLACIER | 99.999999999% | 99.99% (还原对象后) | GLACIER 对象不可用于实时访问。您必须先还原存档对象,然后才可以访问它们 |
RRS | 99.99% | 99.99% | 无 |
启用版本控制后,S3对存储桶请求的503响应显著增加
如果启用版本控制后,S3对存储桶的 PUT或DELETE对象请求的503慢速响应数量显著增加,那么存储桶中可能有一个或多个对象有数以百万计的版本。如果对象有数以百万计的版本,S3会自动限制对该存储桶的请求,以防止客户的请求流量过多,但也可能会妨碍对该存储桶的其他请求.要确定哪些S3对象有数以百万计的版本,可用S3清单工具。清单工具可以生成一份报告,提供存储桶中对象的平面文件列表
键
键是指存储桶中对象的唯一标识符。存储桶内的每个对象都只能有一个键。由于将存储桶、键和版本ID 组合在一起可唯一标识每个对象,可将S3 视为一种“存储桶+键+版本”与对象本身间的基本数据映射。将 Web 服务终端节点、存储桶名、键和版本 (可选) 组合在一起,可唯一地寻址S3 中的每个对象。例如,在 URL http://doc.s3.amazonaws.com/2006-03-01/AmazonS3.wsdl 中,“doc”是存储桶的名称,而“2006-03-01/AmazonS3.wsdl”是键。
有关对象键的更多信息,请参阅对象键。
区域
您可选择一个地理区域供S3存储您创建的存储桶。您可选择一个区域,以便优化延迟、尽可能降低成本或满足法规要求。在某一区域存储的对象将一直留在该区域,除非您特意将其传输到另一区域。
有关 Amazon S3 区域和终端节点的列表,请参阅 AWS 一般参考 中的区域和终端节点。
S3数据一致性模型
S3在所有区域为S3存储桶中的新对象的PUTS提供写后读一致性,但要注意,如果在创建对象前对键名发出HEAD或GET请求 (查看该对象是否存在)S3提供写后读最终一致性。
S3在所有区域提供最终一致性用于覆盖PUTS和DELETES。
单个键的更新是原子更新。例如,如果您对一个现有键执行PUT操作,则后续读取可能会返回旧数据或已更新的数据,但它永远不会返回损坏的数据或部分数据。
S3通过在卓越亚马逊数据中心内的多个服务器间复制数据,从而实现高可用。如果PUT请求成功,则数据已安全存储。但有关更改的信息必须在S3间进行复制,这可能需要一些时间,因此您可能会观察到以下行为:
- 这是一个过程,会将一个新对象写入S3,并立即列出其存储桶内的键。在充分传播此更改前,此对象可能不会显示在列表
- 这是一个过程,会替换一个现有对象,并立即尝试读取此对象。在充分传播此更改前,S3可能会返回先前的数据
- 这是一个过程,会删除一个现有的对象,并立即尝试读取此对象。在充分传播此删除前,S3可能会返回删除的数据
- 这是一个过程,会删除一个现有的对象,并立即列出其存储桶内的键。在充分传播此删除前,S3可能会列出删除的对象
注意: S3目前不支持对象锁定。如果同时对同一键发出2个PUT请求,则以带有最新时间戳的请求为准。如果这会导致问题,您需在应用程序中创建对象锁定机制。
更新基于键值; 无法跨键值实现原子更新。例如,无法根据一个键值的更新对另一键值进行更新,除非将此功能设计到应用程序
最终一致性读取 & 一致性读取
最终一致性读取 | 一致性读取 |
---|---|
过时读取可能性 | 无过时读取 |
最低读取延迟 | 潜在的更高读取延迟 |
最高读取吞吐量 | 潜在的更低读取吞吐量 |
存储类别
S3 提供了一系列存储类,适合不同的使用情形。其中包括适用于经常访问的数据的S3 STANDARD; 适用于长期需要但访问频率不太高的数据的S3 STANDARD_IA,以及适用于长期存档的GLACIER。
有关更多信息,请参阅 存储类别。
存储桶策略
基于各种条件,包括S3操作、请求者、资源和请求的其他方面 (e.g: IP地址),存储桶策略可提供对存储桶和对象的集中访问控制。这些策略使用访问策略语言进行描述且允许对许可进行集中管理。附加到存储桶的许可适用于该存储桶中的所有对象。
个人和公司都可用存储桶策略。在公司向S3注册时,它们会创建一个账户。然后,该公司即等同于此账户。账户在财务上承担支付公司 (及其员工) 所创建的 Amazon 资源的责任。账户有权基于各种条件,授予存储桶策略许可以及分配员工许可。例如,账户可以创建一个策略,授予用户对以下内容的写入权限:
- 特殊的 S3 存储桶
- 从账户的企业网络
- 在工作时间
账户不仅可以授予用户有限的读写访问权限,还可以允许其他人创建和删除存储桶。账户允许多个现场办公室将他们的日常报告存储在单个存储桶中,并使每个办公室仅可以从办公室的IP地址范围写入特定的名称集 (e.g: “Nevada/*”或“Utah/*”)。
与仅可为单个对象添加 (授予) 许可的访问控制列表不同,策略可以为存储桶内的所有对象 (或子集) 添加或拒绝许可。在一个请求中,账户可以为存储桶内任意数量的对象设置权限。账户可对Amazon 资源名称 (ARN) 和其他值使用通配符 (类似于正则),从而控制对以常见前缀开头或以指定扩展名结尾的对象组的访问权限。
仅允许存储桶拥有者将策略与存储桶关联。采用访问策略语言编写的策略将基于以下条件允许或拒绝请求:
- S3存储桶操作 (如
PUT ?acl)
和对象操作 (如PUT Object
或GET Object
) - 请求者
- 在策略中指定的条件
账户可以基于特定的S3操作 (如 GetObject
、GetObjectVersion
、DeleteObject
或 DeleteBucket
) 控制访问权限。
这些条件可以是IP地址、CIDR 表示中的 IP 地址范围、日期、用户代理、HTTP 引用站点和传输 (HTTP 和 HTTPS)。
有关更多信息,请参阅 使用存储桶策略和用户策略。
AWS Identity and Access Management
例如,您可以将 IAM 用于S3,控制用户或用户组对您的 AWS 账户所拥有S3 存储段的具体部分的访问类型。
有关 IAM 的更多信息,请参阅下文:
操作
通过 API 执行的最常见操作:
- 创建存储桶 – 创建和命名要在其中存储对象的您自己的存储桶。
- 写入对象 – 通过创建或覆盖对象存储数据。在编写对象时,在存储桶的命名空间中指定唯一键值。此时,也适合为对象指定任何您想要的访问控制。
- 读取对象 – 读回数据。您可以通过 HTTP 或 BitTorrent 下载数据。
- 删除对象 – 删除您的某些数据。
- 列出键 – 列出包含在某个存储桶中的键。您可以基于前缀筛选键
创建请求
与S3的每一次交互都是经身份验证或匿名的。身份验证是对尝试访问Amazon Web Services (AWS) 产品的请求者身份进行验证的过程。经身份验证的请求必须包含可验证请求发送者的签名值。签名值的一部分是从请求者的AWS访问密钥 (访问密钥ID和秘密访问密钥) 生成的。有关创建访问密钥的更多信息,请参阅如何获取安全凭证?
AWS 账户访问密钥
账户访问密钥提供对账户拥有的 AWS 资源的完全访问权限。以下是访问密钥示例:
- 访问密钥 ID (20个字符的字母数字字符串)。e.g: AKIAIOSFODNN7EXAMPLE
- 秘密访问密钥 (40 个字符的字符串)。e.g: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
访问密钥 ID 可唯一标识 AWS 账户。可用这些访问密钥向S3发送经身份验证的请求。
IAM 用户访问密钥
您可为公司创建一个 AWS 账户;但组织中可能有多个员工需访问组织的 AWS 资源。共享您的 AWS 账户访问密钥会降低安全性,但为每个员工创建单独的 AWS 账户可能也不太实际。此外,您也可能无法轻松地共享资源 (e.g: 存储桶和对象),因为它们由不同账户所拥有。要共享资源,您必须授予许可,这意味着需要额外的工作。
在这些情况中,您可用IAM在您的 AWS 账户下创建具有其自己的访问密钥的用户,然后附加 IAM 用户策略以授予这些用户合适的资源访问许可。为更好地管理这些用户,IAM允许您创建用户组并授予适用于组中所有用户的组级许可。
这些用户被称为 IAM 用户,您可在 AWS 内创建和管理这些用户。父账户将控制用户访问 AWS 的权限。父 AWS 账户负责控制和支付 IAM 用户创建的任何资源。这些IAM用户可用自己的安全凭证向S3 发送经身份验证的请求。有关在 AWS 账户下创建和管理用户的更多信息,请参阅 AWS Identity and Access Management 产品详细信息页面
临时安全凭证
除创建具有自己的访问密钥的IAM用户外,IAM还允许您向任何IAM用户授予临时安全凭证 (临时访问密钥和安全令牌),以便这些用户可以访问您的AWS服务和资源。您也可在AWS外的系统中管理用户。这些用户称为联合身份用户。此外,用户还可以是您创建的能访问您的 AWS 资源的应用程序。
IAM提供了 AWS Security Token Service API,供您用于请求临时安全凭证。您可用 AWS STS API 或 AWS 开发工具包来请求这些凭证。API将返回临时安全凭证 (访问密钥 ID 和秘密访问密钥) 和安全令牌。这些凭证仅在您请求它们时指定的持续时间内有效。使用访问密钥ID和私有密钥的方法与您在使用 AWS 账户或 IAM 用户访问密钥发送请求时使用它们的方法相同。此外,您还必须在每个发送至S3 的请求中包含令牌。
IAM 用户可以请求这些临时安全凭证以供自己使用,也可分发给联合身份用户或应用程序使用。请求适用于联合身份用户的临时安全凭证时,您必须提供用户名称和 IAM 策略 (定义需要与这些临时安全凭证关联的许可)。联合身份用户可获取的许可不能超过请求临时凭证的父IAM用户的许可。
您可用上述临时安全凭证对S3发出请求。API库会使用这些凭证计算必要的签名值,以便对您的请求进行身份验证。如果您使用过期凭证发送请求,S3会拒绝。
有关在REST API请求中使用临时安全凭证对请求进行签名的信息,请参阅 签署和对 REST 请求进行身份验证。有关使用 AWS 开发工具包发送请求的信息,请参阅 使用 AWS 开发工具包创建请求
有关 IAM 对临时安全凭证的支持的更多信息,请参阅临时安全凭证
为提高安全性,您可通过配置存储桶策略,要求在访问您的S3资源时进行多因素身份验证 (MFA)。有关信息,请参阅 添加存储桶策略以请求 MFA。在要求进行 MFA 才能访问您的S3 资源后,访问这些资源的唯一方式是提供使用 MFA 密钥创建的临时凭证。有关更多信息,请参阅AWS Multi-Factor Authentication和配置受 MFA 保护的 API 访问
请求终端节点
您可向服务的预定义终端节点发送 REST 请求。有关所有 AWS 服务及其相应终端节点的列表,请参阅区域和终端节点
通过IPv6向S3发出请求
S3双堆栈终端节点支持通过 IPv6 和 IPv4 向 S3 存储桶发出请求。通过 IPv6 访问S3 不额外收费。
要通过 IPv6 向 S3 存储桶发出请求,需用双堆栈终端节点。
下面是在通过 IPv6 访问存储桶前应了解的部分事项:
- 访问存储桶的客户端和网络必须支持使用IPv6
- 虚拟托管类型和路径类型请求必须都受支持,以便进行IPv6访问
- 如果您在IAM用户或存储桶策略中使用源IP地址筛选,则需更新策略以包括IPv6地址范围
- 如果使用 IPv6,服务器访问日志文件以 IPv6 格式输出IP地址。您需对用于分析S3日志文件的现有工具、脚本和软件进行更新,以便它们能够分析IPv6格式的
Remote IP
地址
无论是通过 IPv6 还是 IPv4 访问S3,S3 API操作的工作方式都是一样的。性能也应该是相同的。
如果使用 REST API,您是直接访问双堆栈终端节点。
如果用AWS CLI(AWS Command Line Interface)和 AWS 开发工具包,可用参数或标志以更改为双堆栈终端节点。还可在配置文件中直接将双堆栈终端节点指定为覆盖S3终端节点。
您可通过以下任一方式,使用双堆栈终端节点通过IPv6访问存储桶:
- AWS CLI,请参阅从 AWS CLI 使用双堆栈终端节点。
- AWS 开发工具包,请参阅从 AWS 开发工具包使用双堆栈终端节点。
- REST API,请参阅通过使用 REST API 向双堆栈终端节点发出请求。
通过 IPv6 访问 S3 存储桶时,以下功能当前不受支持:
- S3 存储桶的静态网站托管
- BitTorrent
在使用 IPv6 访问存储桶前,您必须确保用于 IP 地址筛选的所有 IAM 用户或 S3 存储桶策略已更新为包括 IPv6 地址范围。在开始使用IPv6时,未更新为处理 IPv6 地址的 IP 地址筛选策略可能导致客户端错误地丢失或获得存储桶访问权。
筛选 IP 地址的 IAM 策略使用 IP 地址条件运算符。下面的存储桶策略通过使用 IP 地址条件运算符确定允许的地址范围为 54.240.143.*IPv4 。此范围外的所有 IP 地址对存储桶 (examplebucket
) 的访问都会被拒绝。由于所有 IPv6 地址都在允许范围外,此策略会阻止 IPv6 地址访问 examplebucket
{ "Version": "2012-10-17", "Statement": [ { "Sid": "IPAllow", "Effect": "Allow", "Principal": "*", "Action": "s3:*", "Resource": "arn:aws:s3:::examplebucket/*", "Condition": { "IpAddress": {"aws:SourceIp": "54.240.143.0/24"} } } ] }
可将存储桶策略的 Condition
元素修改为同时允许 IPv4 (54.240.143.0/24
) 和 IPv6 (2001:DB8:1234:5678::/64
) 地址范围(见以下示例)。
"Condition": { "IpAddress": { "aws:SourceIp": [ "54.240.143.0/24", "2001:DB8:1234:5678::/64" ] } }
建议您用组织的 IPv6 地址范围及现有的 IPv4 地址范围来更新您的 IAM 策略。有关同时允许通过 IPv6 和 IPv4 进行访问的存储桶策略示例,请参阅限制对特定 IP 地址的访问权限
您可在 https://console.aws.amazon.com/iam/ 使用 IAM 控制台检查您的 IAM 用户策略
如果使用 Linux/Unix 或 Mac OS X,则通过使用下例所示的 curl
命令,可测试您能否通过 IPv6 访问双堆栈终端节点。
curl -v http://s3.dualstack.us-west-2.amazonaws.com/
您获得的信息如下所示。如果通过IPv6连接,则连接的IP地址将会是 IPv6 地址
* About to connect() to s3-us-west-2.amazonaws.com port 80 (#0) * Trying IPv6 address...
connected * Connected to s3.dualstack.us-west-2.amazonaws.com (IPv6 address) port 80 (#0) >
GET / HTTP/1.1 > User-Agent: curl/7.18.1 (x86_64-unknown-linux-gnu) libcurl/7.18.1
OpenSSL/1.0.1t zlib/1.2.3 > Host: s3.dualstack.us-west-2.amazonaws.com
如果使用Win7,则通过使用下例所示的 ping
命令,可测试您能否通过 IPv6 或 IPv4 访问双堆栈终端节点
ping ipv6.s3.dualstack.us-west-2.amazonaws.com
当您向双堆栈终端节点发出请求时,存储桶URL解析为 IPv6 或 IPv4 地址
当用REST API时,您通过使用终端节点名称 (URI) 直接访问S3终端节点。通过使用虚拟托管类型或路径类型终端节点名称,您可通过双堆栈终端节点访问S3存储桶。S3只支持区域双堆栈终端节点名称,这意味着,您必须在名称中指定区域。
双堆栈虚拟托管类型和路径类型终端节点名称使用以下命名惯例:
- 虚拟托管型双堆栈终端节点:
bucketname
.s3.dualstack.aws-region
.amazonaws.com - 路径型双堆栈终端节点:s3.dualstack.
aws-region
.amazonaws.com/bucketname
您可对双堆栈终端节点使用传输加速
如果用AWS CLI和 AWS 开发工具包,可用参数或标志以更改为双堆栈终端节点。还可在配置文件中直接将双堆栈终端节点指定为覆盖S3 终端节点
在AWS Config文件中的配置文件中将配置值use_dualstack_endpoint
设置为true
,使 s3
和 s3api
AWS CLI 命令发出的所有S3 请求定向到指定区域的双堆栈终端节点。您可在配置文件或命令中用--region
指定区域。
通过AWS CLI使用双堆栈终端节点时,支持path
和virtual
寻址类型。配置文件中设置的寻址类型控制着主机名或 URL 中是否包含存储桶名称。默认,CLI 尝试使用虚拟类型,但如果需要,会改为使用路径类型
也可用命令进行配置更改,如下例所示,在默认配置文件中将use_dualstack_endpoint
设置为true
,将addressing_style
设置为virtual
$ aws configure set default.s3.use_dualstack_endpoint true $ aws configure set default.s3.addressing_style virtual
如果需只对指定的 AWS CLI命令(并非所有命令)使用双堆栈终端节点,可用以下任一方法:
- 将任何
s3
或s3api
命令的--endpoint-url
参数设置为https://s3.dualstack.
或aws-region
.amazonaws.comhttp://s3.dualstack.
来对每条命令使用双堆栈终端节点aws-region
.amazonaws.com
$ aws s3api list-objects --bucket bucketname --endpoint-url https://s3.dualstack.aws-region.amazonaws.com
- 在AWS Config文件中设置单独的配置文件。e.g: 创建一个将
use_dualstack_endpoint
设置为true
的配置文件和一个不设置use_dualstack_endpoint
的配置文件。在运行命令时,根据是否需要使用双堆栈终端节点来指定要使用的配置文件
使用AWS CLI时,当前不能对双堆栈终端节点使用传输加速(但即将推出)
以下示例演示如何使用AWS SDK for Java在创建S3客户端时启用双堆栈终端节点
import com.amazonaws.AmazonServiceException;
import com.amazonaws.SdkClientException;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
public class DualStackEndpoints {
public static void main(String[] args) {
String clientRegion = "*** Client region ***";
String bucketName = "*** Bucket name ***";
try {
// Create an Amazon S3 client with dual-stack endpoints enabled.
AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
.withCredentials(new ProfileCredentialsProvider())
.withRegion(clientRegion)
.withDualstackEnabled(true).build();
s3Client.listObjects(bucketName);
} 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();
}
}
}
如果要在 Windows 上用AWS SDK for Java,可能必须设置以下 Java 虚拟机 (JVM) 属性
java.net.preferIPv6Addresses=true
使用 AWS 开发工具包创建请求
每个 AWS 开发工具包都使用开发工具包特有的凭证提供程序链来查找和使用凭证,并代表凭证所有者执行操作。所有这些凭证提供程序链的共同点是,它们都会寻找您的本地 AWS 凭证文件。
为 AWS 开发工具包配置凭证的最简单方法是使用 AWS 凭证文件。如果您使用AWS CLI,可以按以下步骤设置本地凭证文件:
- 登录 AWS 管理控制台 并通过以下网址打开 IAM 控制台 https://console.aws.amazon.com/iam/
- 创建一个新用户,其权限仅限于您希望您的代码有权访问的服务和操作
- 选择 Download .csv 以保存 AWS 凭证的本地副本
- 在您的计算机上,导航至主目录,并创建
.aws
目录。在基于 Unix 的系统上,它在以下位置:~/.aws。
在 Windows 上,它在以下位置:%HOMEPATH%\.aws
- 在
.aws
目录中,创建名为credentials
的新文件 - 打开您从 IAM 控制台中下载的凭证 .csv 文件,并用以下格式将其内容复制到
credentials
文件:[default] aws_access_key_id = your_access_key_id aws_secret_access_key = your_secret_access_key
- 保存
credentials
文件,并删除在步骤 3 中下载的 .csv 文件
要用 AWS 账户或 IAM 用户凭证向S3发出经身份验证的请求,请执行以下操作:
- 使用
AmazonS3ClientBuilder
类创建AmazonS3Client
实例 - 执行
AmazonS3Client
方法之一,以向 Amazon S3 发送请求。客户端将通过您提供的凭证生成所需的签名并将其包含在请求中
IAM 用户或 AWS 账户可用AWS SDK for Java请求临时安全凭证,然后用这些凭证访问S3。在指定会话持续时间结束后,这些凭证将过期。要用 IAM 临时安全凭证,请执行以下操作:
- 创建
AWSSecurityTokenServiceClient
实例 - 通过调用安全令牌服务 (STS) 客户端的
assumeRole()
代入所需角色 - 通过调用 STS 客户端的
getSessionToken()
开始会话。可用GetSessionTokenRequest
对象向此方法提供会话信息, 此方法将返回临时安全凭证 - 将临时安全凭证打包到
BasicSessionCredentials
对象。可用此对象向您的S3客户端提供临时安全凭证 - 使用临时安全凭证创建
AmazonS3Client
实例。 可用此客户端向S3发送请求。如果使用过期凭证发送请求,S3将返回错误
如果用 AWS 账户安全凭证获取临时安全凭证,则临时凭证的有效期只有1小时。只有当您使用 IAM 用户凭证请求会话时,您才可以指定会话持续时间。
以下示例列出指定存储桶中的一组对象键。该示例将为2小时的会话获取临时安全凭证,然后用这些凭证向S3发送经身份验证的请求
import com.amazonaws.AmazonServiceException;
import com.amazonaws.SdkClientException;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicSessionCredentials;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.ObjectListing;
import com.amazonaws.services.securitytoken.AWSSecurityTokenService;
import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClientBuilder;
import com.amazonaws.services.securitytoken.model.AssumeRoleRequest;
import com.amazonaws.services.securitytoken.model.Credentials;
import com.amazonaws.services.securitytoken.model.GetSessionTokenRequest;
import com.amazonaws.services.securitytoken.model.GetSessionTokenResult;
public class MakingRequestsWithIAMTempCredentials {
public static void main(String[] args) {
String clientRegion = "*** Client region ***";
String roleARN = "*** ARN for role to be assumed ***";
String roleSessionName = "*** Role session name ***";
String bucketName = "*** Bucket name ***";
try {
// Creating the STS client is part of your trusted code. It has
// the security credentials you use to obtain temporary security credentials.
AWSSecurityTokenService stsClient = AWSSecurityTokenServiceClientBuilder.standard()
.withCredentials(new ProfileCredentialsProvider())
.withRegion(clientRegion)
.build();
// Assume the IAM role. Note that you cannot assume the role of an AWS root account;
// Amazon S3 will deny access. You must use credentials for an IAM user or an IAM role.
AssumeRoleRequest roleRequest = new AssumeRoleRequest()
.withRoleArn(roleARN)
.withRoleSessionName(roleSessionName);
stsClient.assumeRole(roleRequest);
// Start a session.
GetSessionTokenRequest getSessionTokenRequest = new GetSessionTokenRequest();
// The duration can be set to more than 3600 seconds only if temporary
// credentials are requested by an IAM user rather than an account owner.
getSessionTokenRequest.setDurationSeconds(7200);
GetSessionTokenResult sessionTokenResult = stsClient.getSessionToken(getSessionTokenRequest);
Credentials sessionCredentials = sessionTokenResult.getCredentials();
// Package the temporary security credentials as a BasicSessionCredentials object
// for an Amazon S3 client object to use.
BasicSessionCredentials basicSessionCredentials = new BasicSessionCredentials(
sessionCredentials.getAccessKeyId(), sessionCredentials.getSecretAccessKey(),
sessionCredentials.getSessionToken());
// Provide temporary security credentials so that the Amazon S3 client
// can send authenticated requests to Amazon S3. You create the client
// using the basicSessionCredentials object.
AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(basicSessionCredentials))
.withRegion(clientRegion)
.build();
// Verify that assuming the role worked and the permissions are set correctly
// by getting a set of object keys from the bucket.
ObjectListing objects = s3Client.listObjects(bucketName);
System.out.println("No. of Objects: " + objects.getObjectSummaries().size());
}
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();
}
}
}
您可以为联合身份用户和应用程序提供临时安全凭证,以便它们可以发送经身份验证的请求,从而访问 AWS 资源。请求这些临时凭证时,必须提供用户名和 IAM 策略 (描述要授予的资源权限)。默认,会话持续时间为1小时。您可在为联合身份用户和应用程序请求临时安全凭证时,显式地设置其他持续时间值。
为提高请求适用于联合身份用户和应用程序的临时安全凭证时的安全性,建议使用仅具有所需访问权限的专用 IAM 用户。创建的临时用户可获取的权限不能超过请求临时安全凭证的 IAM 用户
要提供安全凭证并发送经身份验证的请求以访问资源,请执行以下操作:
- 创建
AWSSecurityTokenServiceClient
实例 - 通过调用STS客户端的
getFederationToken()
启动会话。提供会话信息,包括要附加到临时凭证的用户名和 IAM 策略。您可提供可选的会话持续时间。 此方法将返回临时安全凭证 - 将临时安全凭证打包在
BasicSessionCredentials
对象的实例中。可用此对象向您的S3客户端提供临时安全凭证 - 使用临时安全凭证创建
AmazonS3Client
实例。 可用此客户端向S3 发送请求。如果使用过期的凭证发送请求, S3将返回错误
在以下示例中,将为联合身份用户的时长2小时的会话获取临时安全凭证,然后使用这些凭证向S3发送经身份验证请求。要运行该示例,需创建具有附加策略 (允许用户请求临时安全凭证和列出 AWS 资源) 的 IAM 用户。以下策略将实现此操作:
{
"Statement":[{
"Action":["s3:ListBucket",
"sts:GetFederationToken*"
],
"Effect":"Allow",
"Resource":"*"
}
]
}
创建 IAM 用户并附加上述策略后,可运行以下示例:
import java.io.IOException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.SdkClientException;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicSessionCredentials;
import com.amazonaws.auth.policy.Policy;
import com.amazonaws.auth.policy.Resource;
import com.amazonaws.auth.policy.Statement;
import com.amazonaws.auth.policy.Statement.Effect;
import com.amazonaws.auth.policy.actions.S3Actions;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.securitytoken.AWSSecurityTokenService;
import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClientBuilder;
import com.amazonaws.services.securitytoken.model.Credentials;
import com.amazonaws.services.securitytoken.model.GetFederationTokenRequest;
import com.amazonaws.services.securitytoken.model.GetFederationTokenResult;
import com.amazonaws.services.s3.model.ObjectListing;
public class MakingRequestsWithFederatedTempCredentials {
public static void main(String[] args) throws IOException {
String clientRegion = "*** Client region ***";
String bucketName = "*** Specify bucket name ***";
String federatedUser = "*** Federated user name ***";
String resourceARN = "arn:aws:s3:::" + bucketName;
try {
AWSSecurityTokenService stsClient = AWSSecurityTokenServiceClientBuilder
.standard()
.withCredentials(new ProfileCredentialsProvider())
.withRegion(clientRegion)
.build();
GetFederationTokenRequest getFederationTokenRequest = new GetFederationTokenRequest();
getFederationTokenRequest.setDurationSeconds(7200);
getFederationTokenRequest.setName(federatedUser);
// Define the policy and add it to the request.
Policy policy = new Policy();
policy.withStatements(new Statement(Effect.Allow)
.withActions(S3Actions.ListObjects)
.withResources(new Resource(resourceARN)));
getFederationTokenRequest.setPolicy(policy.toJson());
// Get the temporary security credentials.
GetFederationTokenResult federationTokenResult = stsClient.getFederationToken(getFederationTokenRequest);
Credentials sessionCredentials = federationTokenResult.getCredentials();
// Package the session credentials as a BasicSessionCredentials
// object for an Amazon S3 client object to use.
BasicSessionCredentials basicSessionCredentials = new BasicSessionCredentials(
sessionCredentials.getAccessKeyId(),
sessionCredentials.getSecretAccessKey(),
sessionCredentials.getSessionToken());
AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(basicSessionCredentials))
.withRegion(clientRegion)
.build();
// To verify that the client works, send a listObjects request using
// the temporary security credentials.
ObjectListing objects = s3Client.listObjects(bucketName);
System.out.println("No. of Objects = " + objects.getObjectSummaries().size());
}
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();
}
}
}
使用 REST API 创建请求
用 REST API 创建请求时,可用S3终端节点的虚拟托管类型和路径类型URI
下面是要求从名为 examplebucket 的存储桶删除 puppy.jpg
文件的虚拟托管类型请求的示例
DELETE /puppy.jpg HTTP/1.1
Host: examplebucket.s3-us-west-2.amazonaws.com
Date: Mon, 11 Apr 2016 12:00:00 GMT
x-amz-date: Mon, 11 Apr 2016 12:00:00 GMT
Authorization: authorization string
下面是同一请求的路径类型版本示例
DELETE /examplebucket/puppy.jpg HTTP/1.1
Host: s3-us-west-2.amazonaws.com
Date: Mon, 11 Apr 2016 12:00:00 GMT
x-amz-date: Mon, 11 Apr 2016 12:00:00 GMT
Authorization: authorization string
S3支持在所有区域进行虚拟托管式和路径式访问。但路径式语法要求在尝试访问存储段时必须使用特定于地区的终端节点。例如,如果您有一个位于 欧洲(爱尔兰) 区域的名为 mybucket
的存储桶,您希望用路径式语法且对象名为 puppy.jpg
,则正确的 URI 为 http://s3-eu-west-1.amazonaws.com/mybucket/puppy.jpg
您将收到一个“HTTP 响应代码 307 临时重定向”错误和一条消息,该消息指出当您尝试使用含有以下一种内容的路径式语法来访问美国东部 (弗吉尼亚北部) 区域之外的存储桶时,正确的资源 URI 为:
http://s3.amazonaws.com
- 区域的终端节点不同于存储桶所在的终端节点。例如,对在美国西部(加利福尼亚北部) 区域创建的存储桶使用
http://s3-eu-west-1.amazonaws.com
用 REST API 时,可通过使用虚拟托管类型或路径类型终端节点名称 (URI) 直接访问双堆栈终端节点。所有S3 双堆栈终端节点名称中都包含区域。与标准的仅支持 IPv4 的终端节点不同,虚拟托管类型和路径类型终端节点都使用特定于区域的终端节点名称
如下例所示,您可在REST请求中使用虚拟托管类型终端节点,该示例从名为 puppy.jpg
的存储桶检索 examplebucket
对象
GET /puppy.jpg HTTP/1.1
Host: examplebucket.s3.dualstack.us-west-2.amazonaws.com
Date: Mon, 11 Apr 2016 12:00:00 GMT
x-amz-date: Mon, 11 Apr 2016 12:00:00 GMT
Authorization: authorization string
如下例所示,也可在请求中使用路径类型终端节点
GET /examplebucket/puppy.jpg HTTP/1.1
Host: s3.dualstack.us-west-2.amazonaws.com
Date: Mon, 11 Apr 2016 12:00:00 GMT
x-amz-date: Mon, 11 Apr 2016 12:00:00 GMT
Authorization: authorization string
一般,虚拟托管指从单个 Web 服务器为多个 Web 站点提供服务的做法。区分站点的一种方法是通过使用请求的显式主机名,而不只是 URI 的路径名称部分。普通的S3 REST请求使用“请求-URI”路径的第一个斜杠分隔部分指定存储桶。或通过使用 HTTP Host
标头,在 REST API 调用中使用S3 虚拟托管对存储桶进行寻址。事实上,S3会将 Host
解释为可在 http://
上自动访问大多数存储桶 (对于有限类型的请求)。此外,通过使用注册域名来命名存储桶,并将该名称设为S3 的DNS别名,您可完全自定义S3 资源的URL,例如:bucketname
.s3.amazonaws.comhttp://my.bucketname.com/
除自定义 URL 的好处外,虚拟托管的另一个好处是能发布到存储桶的虚拟服务器的“根目录”。此功能很重要,因为许多现有应用程序在此标准位置搜索文件。例如,favicon.ico
、robots.txt
、crossdomain.xml
都应在根目录下
S3支持在所有区域进行虚拟托管和路径式访问。但路径式语法要求在尝试访问存储段时必须使用特定于地区的终端节点
如果您使用美国东部 (弗吉尼亚北部) 终端节点 (s3.amazonaws.com),而不是区域特定的终端节点 (例如 s3-eu-west-1),则在默认情况下S3 会将任何虚拟托管式请求路由到美国东部 (弗吉尼亚北部) 区域)。当您在任何区域创建存储桶时,S3 都将更新 DNS 以将请求重新路由到正确的位置,这可能会花费一些时间。同时,将应用默认规则,您的虚拟托管式请求也会进入美国东部 (弗吉尼亚北部) 区域,S3将使用 HTTP 307 redirect 将其重定向到正确的区域
当通过 SSL 使用虚拟托管式存储桶时,SSL 通配符证书仅匹配不包含句点的存储桶。要解决此问题,请使用HTTP或编写自己的证书验证逻辑
只要您的 GET
请求不使用 SSL 终端节点,您就可通过使用 HTTP Host
标头为请求指定存储桶。REST请求中的 Host
标头解释如下:
- 如果
Host
标头被省略,或其值为“s3.amazonaws.com”,则该请求的存储桶将成为“Request-URI”的第一个斜杠分隔的部分,且该请求的键值将成为“Request-URI”的其余部分。省略主机标头仅对HTTP 1.0 请求有效 - 否则,如果
Host
标头的值以“.s3.amazonaws.com”结尾,则存储桶名称是Host
标头值中从开头到“.s3.amazonaws.com”的部分。该请求的键值为“Request-URI”。此解释将存储桶公开为 s3.amazonaws.com 的子域 - 否则,请求的存储桶是
Host
标头的小写值,请求的键值是“Request-URI”。如果注册的 DNS 名称与存储桶名称相同,且已将该名称配置为S3的别名记录 (CNAME) 别名,则此解释很有用
本示例使用 johnsmith.net
作为存储桶名称,使用 homepage.html
作为密钥名称(路径类型的方法)
http://s3.amazonaws.com/johnsmith.net/homepage.html
请求如下:
GET /johnsmith.net/homepage.html HTTP/1.1
Host: s3.amazonaws.com
本示例使用 johnsmith.net
作为存储桶名称,使用 homepage.html
作为密钥名称(虚拟托管式方法)
http://johnsmith.net.s3.amazonaws.com/homepage.html
请求如下:(虚拟托管式方法要求存储桶名称符合 DNS 要求)
GET /homepage.html HTTP/1.1
Host: johnsmith.net.s3.amazonaws.com
本示例使用 johnsmith.eu
作为 欧洲(爱尔兰) 区域中存储桶的名称,并使用 homepage.html
作为键名称(针对非美国东部 (弗吉尼亚北部) 区域内的存储桶的虚拟托管式方法)
http://johnsmith.eu.s3-eu-west-1.amazonaws.com/homepage.html
请求如下:
GET /homepage.html HTTP/1.1
Host: johnsmith.eu.s3-eu-west-1.amazonaws.com
注意,无论存储桶位于哪个区域,都可用美国东部 (弗吉尼亚北部) 区域终端节点替代区域特定的终端节点
http://johnsmith.eu.s3.amazonaws.com/homepage.html
请求如下:
GET /homepage.html HTTP/1.1
Host: johnsmith.eu.s3.amazonaws.com
本示例用 www.johnsmith.net
作为存储桶名称,用 homepage.html
作为密钥名称。要用此法,必须配置 DNS 名称作为 bucketname
.s3.amazonaws.com 的别名记录别名
http://www.johnsmith.net/homepage.html
请求如下:
GET /homepage.html HTTP/1.1
Host: www.johnsmith.net
根据需要,您可能不希望“s3.amazonaws.com”显示在网站或服务中。例如,如果在S3上托管网站映像,您可能会首选 http://images.johnsmith.net/
,而不是 http://johnsmith-images.s3.amazonaws.com/
存储桶名称必须与CNAME相同。因此,如果创建了别名记录,以便将 http://images.johnsmith.net/filename
映射到 http://images.johnsmith.net.s3.amazonaws.com/filename
,则 images.johnsmith.net
将与 images.johnsmith.net.s3.amazonaws.com
相同
具有 DNS 兼容名称的任何存储桶都可按以下方式引用:http://[
,例如 BucketName
].s3.amazonaws.com/[Filename
]http://images.johnsmith.net.s3.amazonaws.com/mydog.jpg
。通过使用别名记录,可将 images.johnsmith.net
映射到S3 主机名,因此上述 URL 可变为 http://images.johnsmith.net/mydog.jpg
别名记录DNS记录应将您的域名别名设置为适当的虚拟托管式主机名。例如,如果存储桶名称和域名是 images.johnsmith.net
,则别名记录应将别名设置为 images.johnsmith.net.s3.amazonaws.com
.
images.johnsmith.net CNAME images.johnsmith.net.s3.amazonaws.com.
也可以针对 s3.amazonaws.com
设置别名,但可能导致额外的 HTTP 重定向
S3 使用主机名来确定存储桶名称。例如,假定您配置了 www.example.com
作为 www.example.com.s3.amazonaws.com
的别名记录。当您访问 http://www.example.com
时,S3 会收到如下请求:
GET / HTTP/1.1
Host: www.example.com
Date: date
Authorization: signatureValue
因为S3 仅看到原始主机名 www.example.com
,不知道用于解析请求的别名记录映射,所以别名记录和存储桶名称必须相同
可在别名记录中使用任何S3 终端节点。例如,s3-ap-southeast-1.amazonaws.com
可用于 CNAME 中
使用别名记录将主机名与 Amazon S3 存储桶关联
- 选择属于您控制的域的主机名。本示例使用
images
域的johnsmith.net
子域 - 创建与主机名匹配的存储桶。在本示例中,主机名和存储桶名称是
images.johnsmith.net
- 创建一条 CNAME 记录,它定义主机名作为S3存储桶的别名
使用S3 REST API 的程序既可处理应用程序层上的重定向,也可处理 HTTP层上的重定向。许多HTTP客户端库和用户代理经过配置可自动正确处理重定向;然而,许多其他 HTTP 客户端库和用户代理的重定向实施会不正确或不完整
在依赖库完成重定向要求前,请测试以下案例:
- 验证所有 HTTP 请求标头都已正确地包含在重定向的请求中 (收到重定向后的第2个请求),包括诸如授权和日期等 HTTP 标准
- 验证诸如 PUT 和 DELETE 等非 GET 的重定向运行正常
- 验证大型 PUT 请求正确地遵循了重定向
- 如果需要很长时间才能收到 100-继续响应,请验证 PUT 请求正确地遵循了重定向
当 HTTP 请求方法不是 GET 或 HEAD 时,严格遵循 RFC 2616 的 HTTP 用户代理可能会在遵循重定向前,请求显式确认。自动遵循S3 生成的重定向通常是安全的,因为系统只会发出指向 amazonaws.com 域中主机的重定向,且重定向请求的效果与原始请求的效果相同
要简化重定向处理过程、提高工作效率及避免重复支付与发送重定向请求正文相关的费用,请将您的应用程序配置为对PUT使用 100-继续。当应用程序使用 100-继续时,它不会发送请求正文,直到收到认可。如果根据标头拒绝了消息,则不会发送正文
根据RFC2616,在未知的 HTTP 服务器中使用 Expect: Continue
时,您应直接发送请求正文,不要等待某个无限期的时段。这是因为某些HTTP服务器不能识别100-继续。但如果您的请求包含了 Expect: Continue
,S3能进行识别且将使用临时的100-继续状态或最终的状态代码进行响应。此外,收到临时的100 继续操作指示后,不会发生重定向错误。这可帮助您避免在编写请求正文时,收到重定向响应
下面是用于 quotes.s3.amazonaws.com
存储桶的示例PUT
PUT /nelson.txt HTTP/1.1
Host: quotes.s3.amazonaws.com
Date: Mon, 15 Oct 2007 22:18:46 +0000
Content-Length: 6
Expect: 100-continue
S3 将返回以下内容
HTTP/1.1 307 Temporary Redirect
Location: http://quotes.s3-4c25d83b.amazonaws.com/nelson.txt?rk=8d47490b
Content-Type: application/xml
Transfer-Encoding: chunked
Date: Mon, 15 Oct 2007 22:18:46 GMT
Server: AmazonS3
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>TemporaryRedirect</Code>
<Message>Please re-send this request to the
specified temporary endpoint. Continue to use the
original request endpoint for future requests.
</Message>
<Endpoint>quotes.s3-4c25d83b.amazonaws.com</Endpoint>
<Bucket>quotes</Bucket>
</Error>
客户端将遵循重定向响应并向 quotes.s3-4c25d83b.amazonaws.com
临时终端节点发布新的请求
PUT /nelson.txt?rk=8d47490b HTTP/1.1
Host: quotes.s3-4c25d83b.amazonaws.com
Date: Mon, 15 Oct 2007 22:18:46 +0000
Content-Length: 6
Expect: 100-continue
S3 将返回 100-继续,以指示客户端应继续发送请求正文
HTTP/1.1 100 Continue
客户端将发送请求正文
ha ha\n
S3 将返回最终响应
HTTP/1.1 200 OK
Date: Mon, 15 Oct 2007 22:18:48 GMT
ETag: "a2c8d6b872054293afd41061e93bc289"
Content-Length: 0
Server: AmazonS3
S3应用程序编程接口
S3架构的设计与编程语言无关,它使用我们支持的接口来存储和检索对象。
S3提供REST接口。在REST接口中,元数据在HTTP标头中返回。由于我们仅支持最大4KB的HTTP请求 (不包括正文),因此您能提供的元数据量是受限的。
REST API 是面向S3的HTTP接口。借助REST,您可用标准的HTTP请求创建、提取和删除存储桶和对象。
您可以借助任何支持 HTTP 的工具包来使用REST API。只要对象是匿名可读的,您甚至可以使用浏览器来提取它们。
REST API使用标准的HTTP标头和状态代码,以使标准的浏览器和工具包按预期工作。在某些区域中,我们向HTTP添加了功能 (e.g: 我们添加了标头来支持访问控制)。在这些情况下,我们已尽最大努力使添加的新功能与标准的HTTP使用样式相匹配。
为S3付费
S3定价的设计可让您不必为应用程序的存储需求制定计划。大多数存储提供商会强迫您购买预定量的存储和网络传输容量:如果超过此容量,就会关闭您的服务或对您收取高额的超容量费用。如果没有超过此容量,又要按全部容量支付使用费用。
S3仅照实际使用容量收费,没有任何隐性收费和超容量收费。这为开发人员提供了一种可变成本服务,这种服务可以伴随他们的业务共同发展,同时还可以享受 Amazon 的基础设施成本优势。
在S3中存储任何内容之前,您需注册服务并提供一个每月月底付费时使用的付款方式。开始使用服务时,没有安装费。月底时,将自动通过您的付款方式扣除当月使用费。
有关为 Amazon S3 存储付费的信息,请参阅 Amazon S3 定价
相关服务
一旦将数据加载到S3,便可将其用于我们提供的其他服务。以下可能是您会频繁使用的服务:
- Amazon Elastic Compute Cloud – 此 Web 服务提供云中的虚拟计算资源。有关更多信息,请参阅 Amazon EC2 产品详细信息页面。
- Amazon EMR – 此 Web 服务可让企业、研究人员、数据分析师和开发人员轻松地、经济实惠地处理海量数据。该服务的实现利用了在EC2 和S3 的 Web 规模基础设施上运行的托管Hadoop框架。有关更多信息,请参阅 Amazon EMR 产品详细信息页面。
- AWS Import/Export - 通过AWS Import/Export,您可将存储设备 (如 RAID 驱动器) 寄至 Amazon,我们可以将您的数据 (TB 字节) 上传到S3。有关更多信息,请转到 AWS Import/Export Developer Guide