

 适用于 Java 的 AWS SDK 1.x于2025年 end-of-support 12月31日达到。我们建议您迁移到 [AWS SDK for Java 2.x](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/home.html) 以继续获得新功能、可用性改进和安全更新。

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 使用 IAM 角色授予对 Amazon EC2 上的 AWS 资源的访问权
<a name="java-dg-roles"></a>

必须通过使用由 AWS 颁发的凭证对发送到 Amazon Web Services (AWS) 的所有请求进行加密签名。可以使用 *IAM 角色* 方便地授予对 Amazon EC2 实例上的 AWS 资源的安全访问权。

本主题介绍如何将 IAM 角色与 Amazon EC2 上运行的 Java SDK 应用程序结合使用。有关 IAM 实例的更多信息，请参阅《Amazon EC2 用户指南（适用于 Linux 实例）》中的[适用于 Amazon EC2 的 IAM 角色](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html)。

## 默认提供程序链和 EC2 实例配置文件
<a name="default-provider-chain"></a>

如果您的应用程序使用默认构造函数创建 AWS 客户端，则该客户端将按照以下顺序使用*默认凭证提供程序链* 搜索凭证：

1. Java 系统属性：`aws.accessKeyId` 和 `aws.secretKey`。

1. 系统环境变量：`AWS_ACCESS_KEY_ID` 和 `AWS_SECRET_ACCESS_KEY`。

1. 默认凭证文件 (在不同平台上该文件位于不同位置)。

1. 如果已设置 `AWS_CONTAINER_CREDENTIALS_RELATIVE_URI` 环境变量且安全管理器有权访问该变量，则为通过 Amazon EC2 容器服务传递的凭证。

1. *实例配置文件凭证*，包含在与 EC2 实例的 IAM 角色关联的实例元数据中。

1. 来自环境或容器的 Web 身份令牌凭证。

只有在对 Amazon EC2 实例运行应用程序时，默认提供程序链中的*实例配置文件凭证* 步骤才可用，但在处理 Amazon EC2 实例时，该步骤能够最大限度地简化使用过程并提高安全性。您还可以将 [InstanceProfileCredentialsProvider](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/auth/InstanceProfileCredentialsProvider.html) 实例直接传递给客户端构造函数，这样无需执行整个默认提供程序链即可获取实例配置文件凭证。

例如：

```
AmazonS3 s3 = AmazonS3ClientBuilder.standard()
              .withCredentials(new InstanceProfileCredentialsProvider(false))
              .build();
```

在使用该方法时，SDK 在其实例配置文件中，检索与 Amazon EC2 实例的关联 IAM 角色的关联凭证具有相同权限的临时 AWS 凭证。尽管这些凭证是临时凭证，而且最终会过期，但 `InstanceProfileCredentialsProvider` 会定期为您刷新它们，保证您收到的凭证可继续访问 AWS。

**重要**  
*仅* 在以下情况下执行自动凭证刷新：您使用默认客户端构造函数 (它会创建其自身的 `InstanceProfileCredentialsProvider` 作为默认提供程序链的内容) 时；或者您将 `InstanceProfileCredentialsProvider` 实例直接传递给客户端构造函数时。如果您使用其他方法获取或传送实例配置文件凭证，您将负责检查和刷新过期凭证。

如果客户端构造函数使用凭证提供程序链找不到凭证，它会引发 [AmazonClientException](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/AmazonClientException.html)。

## 演练：将 IAM 角色用于 EC2 实例
<a name="roles-walkthrough"></a>

以下演练将介绍如何使用 IAM 角色从 Amazon S3 中检索对象以管理访问。

### 创建 IAM 角色
<a name="java-dg-create-the-role"></a>

创建授予对 Amazon S3 的只读访问权的 IAM 角色。

1. 打开 [IAM 管理控制台](https://console.aws.amazon.com/iam/home)。

1. 在导航窗格中，选择 **Roles** 和 **Create New Role**。

1. 输入角色名称，然后选择 **Next Step**。请记住此名称，因为在启动 Amazon EC2 实例时会用到它。

1. 在**选择角色类型**页面的 **AWS 服务 角色**下，选择 **Amazon EC2**。

1. 在**设置权限**页面的**选择策略模板**下，选择 **Amazon S3 只读访问权限**，然后选择**下一步**。

1. 在 **Review** 页面上，选择 **Create Role**。

### 启动 EC2 实例并指定您的 IAM 角色
<a name="java-dg-launch-ec2-instance-with-instance-profile"></a>

您可通过 Amazon EC2 控制台或适用于 Java 的 AWS SDK，使用 IAM 角色启动 Amazon EC2 实例。
+ 要使用控制台启动 Amazon EC2 实例，请按照《Amazon EC2 用户指南（适用于 Linux 实例）》[Amazon EC2 Linux 实例入门](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EC2_GetStarted.html)中的说明操作。

  到达**核查实例启动**页面时，选择**编辑实例详细信息**。在 **IAM 角色**中，选择您之前创建的 IAM 角色。按指示完成该过程。
**注意**  
您需要创建或使用现有安全组和密钥对，才能连接到该实例。
+ 要使用适用于 Java 的 AWS SDK 通过 IAM 角色启动 Amazon EC2 实例，请参阅[运行 Amazon EC2 实例](run-instance.md)。

### 创建您的应用程序
<a name="java-dg-remove-the-credentials"></a>

让我们来构建在 EC2 实例上运行的示例应用程序。首先，创建一个目录来用于保存教程文件 (例如，`GetS3ObjectApp`)。

然后，将适用于 Java 的 AWS SDK 库复制到新创建的目录中。如果已将适用于 Java 的 AWS SDK下载到 `~/Downloads` 目录中，可以使用以下命令进行复制：

```
cp -r ~/Downloads/aws-java-sdk-{1.7.5}/lib .
cp -r ~/Downloads/aws-java-sdk-{1.7.5}/third-party .
```

打开一个新文件，将其命名为 `GetS3Object.java` 并添加以下代码：

```
import java.io.*;

import com.amazonaws.auth.*;
import com.amazonaws.services.s3.*;
import com.amazonaws.services.s3.model.*;
import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;

public class GetS3Object {
  private static final String bucketName = "text-content";
  private static final String key = "text-object.txt";

  public static void main(String[] args) throws IOException
  {
    AmazonS3 s3Client = AmazonS3ClientBuilder.defaultClient();

    try {
      System.out.println("Downloading an object");
      S3Object s3object = s3Client.getObject(
          new GetObjectRequest(bucketName, key));
      displayTextInputStream(s3object.getObjectContent());
    }
    catch(AmazonServiceException ase) {
      System.err.println("Exception was thrown by the service");
    }
    catch(AmazonClientException ace) {
      System.err.println("Exception was thrown by the client");
    }
  }

  private static void displayTextInputStream(InputStream input) throws IOException
  {
    // Read one text line at a time and display.
    BufferedReader reader = new BufferedReader(new InputStreamReader(input));
    while(true)
    {
      String line = reader.readLine();
      if(line == null) break;
      System.out.println( "    " + line );
    }
    System.out.println();
  }
}
```

打开一个新文件，将其命名为 `build.xml` 并添加以下行：

```
<project name="Get {S3} Object" default="run" basedir=".">
  <path id="aws.java.sdk.classpath">
    <fileset dir="./lib" includes="**/*.jar"/>
    <fileset dir="./third-party" includes="**/*.jar"/>
    <pathelement location="lib"/>
    <pathelement location="."/>
  </path>

  <target name="build">
  <javac debug="true"
    includeantruntime="false"
    srcdir="."
    destdir="."
    classpathref="aws.java.sdk.classpath"/>
  </target>

  <target name="run" depends="build">
    <java classname="GetS3Object" classpathref="aws.java.sdk.classpath" fork="true"/>
  </target>
</project>
```

构建并运行修改后的程序。请注意，该程序中未存储凭证。所以，除非您已经指定 AWS 凭证，否则代码会引发 `AmazonServiceException`。例如：

```
$ ant
Buildfile: /path/to/my/GetS3ObjectApp/build.xml

build:
  [javac] Compiling 1 source file to /path/to/my/GetS3ObjectApp

run:
   [java] Downloading an object
   [java] AmazonServiceException

BUILD SUCCESSFUL
```

### 传输已编译的程序到您的 EC2 实例
<a name="java-dg-transfer-compiled-program-to-ec2-instance"></a>

使用安全复制 (Amazon EC2 ** ``)，将程序连同 ** 库传输到适用于 Java 的 AWS SDK 实例。该命令序列与以下序列相似。

```
scp -p -i {my-key-pair}.pem GetS3Object.class ec2-user@{public_dns}:GetS3Object.class
scp -p -i {my-key-pair}.pem build.xml ec2-user@{public_dns}:build.xml
scp -r -p -i {my-key-pair}.pem lib ec2-user@{public_dns}:lib
scp -r -p -i {my-key-pair}.pem third-party ec2-user@{public_dns}:third-party
```

**注意**  
根据您使用的 Linux 版本，*用户名* 可能是“ec2-user”、“root”或“ubuntu”。要获取实例的公有 DNS 名称，请打开 [EC2 控制台](https://console.aws.amazon.com/ec2/home)并在**描述**选项卡中查找**公有 DNS** 值（例如 `ec2-198-51-100-1.compute-1.amazonaws.com`）。

在上述命令中：
+  `GetS3Object.class` 是已编译的程序
+  `build.xml` 是用于构建和运行您的程序的 Ant 文件
+ `lib` 和 `third-party` 目录是适用于 Java 的 AWS SDK中对应的库文件夹。
+ `-r` 开关指示 `scp` 应该对`library`版本的 `third-party` 和 适用于 Java 的 AWS SDK 目录中的所有内容以递归方式进行复制。
+ `-p` 开关指示 `scp` 在将源文件复制到目标位置时，应保留对应文件的权限。
**注意**  
`-p` 开关仅适用于 Linux、macOS 或 Unix。如果您从 Windows 中复制文件，可能需要使用以下命令在实例上修复文件权限：

```
chmod -R u+rwx GetS3Object.class build.xml lib third-party
```

### 在 EC2 实例上运行示例程序
<a name="java-dg-run-the-program"></a>

要运行程序，请连接到 Amazon EC2 实例。有关更多信息，请参阅《Amazon EC2 用户指南（适用于 Linux 实例）》中的[连接到您的 Linux 实例](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AccessingInstances.html)。

如果 **` ant ` 在您的实例上不可用，请使用以下命令安装它：**

```
sudo yum install ant
```

然后使用 `ant` 运行程序，如下所示：

```
ant run
```

该程序会将 Amazon S3 对象的内容写入命令窗口。