

# 使用 IAM 用户临时凭证发出请求
<a name="AuthUsingTempSessionToken"></a>

 AWS 账户 或 IAM 用户可以请求临时安全证书，然后使用它们来向 Amazon S3 发送经身份验证的请求。本节提供了一些示例，介绍了如何使用 适用于 Java 的 AWS SDK、.NET 和 PHP 获取临时安全证书，以及如何使用这些证书来对您发送至 Amazon S3 的请求进行身份验证。

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

IAM 用户或 AWS 账户 可以使用采用 适用于 Java 的 AWS SDK 的临时安全凭证（请参阅 [提出请求](MakingRequests.md)），然后使用这些凭证访问 Amazon S3。在指定会话持续时间结束后，这些凭证将过期。

默认情况下，会话的持续时间为一个小时。如果您使用了 IAM 用户凭证，则可在请求临时安全凭证时指定持续时间（15 分钟到角色的最长会话持续时间）。有关临时安全凭证的更多信息，请参阅《IAM 用户指南》**中的[临时安全凭证](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html)。有关发出请求的更多信息，请参阅[提出请求](MakingRequests.md)。

**获取临时安全凭证并访问 Amazon S3**

1. 创建 `AWSSecurityTokenService` 类的实例。

1. 通过调用安全令牌服务 (STS) 客户端的 `assumeRole()` 方法，检索所需角色的临时安全凭证。

1. 将临时安全凭证打包到 `BasicSessionCredentials` 对象中。您可以使用此对象来向您的 Amazon S3 客户端提供临时安全凭证。

1. 使用临时安全凭证创建 `AmazonS3Client` 类的实例。您可以使用此客户端向 Amazon S3 发送请求。如果使用过期凭证发送请求，Amazon S3 将返回错误。

**注意**  
如果使用 AWS 账户 安全凭证获取临时安全凭证，则临时凭证的有效期只有一小时。只有当您使用 IAM 用户证书来请求会话时，您才可以指定会话持续时间。

以下示例列出了指定存储桶中的一组对象键。该示例将为会话获取临时安全凭证，然后使用这些凭证向 Amazon S3 发送经身份验证的请求。

如果要使用 IAM 用户凭证测试示例，则必须在 AWS 账户 下创建一个 IAM 用户。有关如何创建 IAM 用户的更多信息，请参阅《IAM 用户指南》**中的[创建您的第一个 IAM 用户和管理员组](https://docs.aws.amazon.com/IAM/latest/UserGuide/getting-started_create-admin-group.html)。

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

```
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.AssumeRoleResult;
import com.amazonaws.services.securitytoken.model.Credentials;

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();

            // Obtain credentials for 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);
            AssumeRoleResult roleResponse = stsClient.assumeRole(roleRequest);
            Credentials sessionCredentials = roleResponse.getCredentials();

            // Create a BasicSessionCredentials object that contains the credentials you
            // just retrieved.
            BasicSessionCredentials awsCredentials = 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 sessionCredentials object.
            AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
                    .withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
                    .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();
        }
    }
}
```

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

IAM 用户或 AWS 账户 可以使用 适用于 .NET 的 AWS SDK 请求临时安全凭证，然后使用这些凭证来访问 Amazon S3。在会话持续时间结束后，这些凭证将过期。

默认情况下，会话的持续时间为一个小时。如果您使用了 IAM 用户凭证，则可在请求临时安全凭证时指定持续时间（15 分钟到角色的最长会话持续时间）。有关临时安全凭证的更多信息，请参阅《IAM 用户指南》**中的[临时安全凭证](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html)。有关发出请求的更多信息，请参阅[提出请求](MakingRequests.md)。

**获取临时安全凭证并访问 Amazon S3**

1. 创建AWS Security Token Service客户端的实例 `AmazonSecurityTokenServiceClient`。

1. 通过调用您在上一步骤中创建的 STS 客户端的 `GetSessionToken` 方法，开始会话。您可以使用 `GetSessionTokenRequest` 对象向此方法提供会话信息。

   此方法将返回您的临时安全凭证。

1. 将临时安全凭证打包在 `SessionAWSCredentials` 对象的实例中。您可以使用此对象来向您的 Amazon S3 客户端提供临时安全凭证。

1. 通过传入临时安全凭证创建 `AmazonS3Client` 类的实例。您可以使用此客户端向 Amazon S3 发送请求。如果您使用过期的凭证发送请求，Amazon S3 将返回错误。

**注意**  
如果使用 AWS 账户 安全凭证获取临时安全凭证，则这些凭证仅在一小时内有效。仅当使用 IAM 用户凭证请求会话时，才能指定会话持续时间。

以下 C\# 示例列出了指定存储桶中的对象键。为了展示这个过程，示例会为默认一小时的会话获取临时安全凭证，然后使用这些凭证来向 Amazon S3 发送经身份验证的请求。

如果要使用 IAM 用户凭证测试示例，则必须在 AWS 账户 下创建一个 IAM 用户。有关如何创建 IAM 用户的更多信息，请参阅《IAM 用户指南》**中的[创建您的第一个 IAM 用户和管理员组](https://docs.aws.amazon.com/IAM/latest/UserGuide/getting-started_create-admin-group.html)。有关发出请求的更多信息，请参阅[提出请求](MakingRequests.md)。

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

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

namespace Amazon.DocSamples.S3
{
    class TempCredExplicitSessionStartTest
    {
        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()
        {
            ListObjectsAsync().Wait();
        }

        private static async Task ListObjectsAsync()
        {
            try
            {
                // Credentials use the default AWS SDK for .NET credential search chain. 
                // On local development machines, this is your default profile.
                Console.WriteLine("Listing objects stored in a bucket");
                SessionAWSCredentials tempCredentials = await GetTemporaryCredentialsAsync();

                // Create a client by providing temporary security credentials.
                using (s3Client = new AmazonS3Client(tempCredentials, bucketRegion))
                {
                    var listObjectRequest = new ListObjectsRequest
                    {
                        BucketName = bucketName
                    };
                    // Send request to Amazon S3.
                    ListObjectsResponse response = await s3Client.ListObjectsAsync(listObjectRequest);
                    List<S3Object> objects = response.S3Objects;
                    Console.WriteLine("Object count = {0}", objects.Count);
                }
            }
            catch (AmazonS3Exception s3Exception)
            {
                Console.WriteLine(s3Exception.Message, s3Exception.InnerException);
            }
            catch (AmazonSecurityTokenServiceException stsException)
            {
                Console.WriteLine(stsException.Message, stsException.InnerException);
            }
        }

        private static async Task<SessionAWSCredentials> GetTemporaryCredentialsAsync()
        {
            using (var stsClient = new AmazonSecurityTokenServiceClient())
            {
                var getSessionTokenRequest = new GetSessionTokenRequest
                {
                    DurationSeconds = 7200 // seconds
                };

                GetSessionTokenResponse sessionTokenResponse =
                              await stsClient.GetSessionTokenAsync(getSessionTokenRequest);

                Credentials credentials = sessionTokenResponse.Credentials;

                var sessionCredentials =
                    new SessionAWSCredentials(credentials.AccessKeyId,
                                              credentials.SecretAccessKey,
                                              credentials.SessionToken);
                return sessionCredentials;
            }
        }
    }
}
```

------
#### [ PHP ]

有关适用于 Ruby 的 AWS 开发工具包 API 的更多信息，请转到[适用于 Ruby 的 AWS 开发工具包 – 版本 2](https://docs.aws.amazon.com/sdkforruby/api/index.html)。

IAM 用户或 AWS 账户 可使用 适用于 PHP 的 AWS SDK 的版本 3 请求临时安全凭证。之后，它可使用临时凭证访问 Amazon S3。这些凭证将在会话持续时间结束时到期。

默认情况下，会话的持续时间为一个小时。如果您使用了 IAM 用户凭证，则可在请求临时安全凭证时指定持续时间（15 分钟到角色的最长会话持续时间）。有关临时安全凭证的更多信息，请参阅《IAM 用户指南》**中的[临时安全凭证](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html)。有关发出请求的更多信息，请参阅[提出请求](MakingRequests.md)。

**注意**  
如果您使用AWS 账户 安全凭证获取临时安全凭证，则临时安全凭证的有效期仅为一个小时。只有当您使用 IAM 用户证书来请求会话时，您才可以指定会话持续时间。

**Example**  
以下 PHP 示例使用临时安全凭证列出指定存储桶中的对象键。该示例将为默认一小时的会话获取临时安全凭证，然后使用这些凭证向 Amazon S3 发送经身份验证的请求。有关适用于 Ruby 的 AWS 开发工具包 API 的更多信息，请转到[适用于 Ruby 的 AWS 开发工具包 – 版本 2](https://docs.aws.amazon.com/sdkforruby/api/index.html)。  
如果要使用 IAM 用户凭证测试示例，则必须在 AWS 账户 下创建一个 IAM 用户。有关如何创建 IAM 用户的信息，请参阅《IAM 用户指南》**中的[创建您的第一个 IAM 用户和管理员组](https://docs.aws.amazon.com/IAM/latest/UserGuide/getting-started_create-admin-group.html)。有关在使用 IAM 用户凭证请求会话时设置会话持续时间的示例，请参阅[使用 IAM 用户临时凭证发出请求](#AuthUsingTempSessionToken)。  

```
 require 'vendor/autoload.php';

use Aws\S3\Exception\S3Exception;
use Aws\S3\S3Client;
use Aws\Sts\StsClient;

$bucket = '*** Your Bucket Name ***';

$sts = new StsClient([
    'version' => 'latest',
    'region' => 'us-east-1'
]);

$sessionToken = $sts->getSessionToken();

$s3 = new S3Client([
    'region' => 'us-east-1',
    'version' => 'latest',
    'credentials' => [
        'key'    => $sessionToken['Credentials']['AccessKeyId'],
        'secret' => $sessionToken['Credentials']['SecretAccessKey'],
        'token'  => $sessionToken['Credentials']['SessionToken']
    ]
]);

$result = $s3->listBuckets();

try {
    // Retrieve a paginator for listing objects.
    $objects = $s3->getPaginator('ListObjects', [
        'Bucket' => $bucket
    ]);

    echo "Keys retrieved!" . PHP_EOL;

    // List objects
    foreach ($objects as $object) {
        echo $object['Key'] . PHP_EOL;
    }
} catch (S3Exception $e) {
    echo $e->getMessage() . PHP_EOL;
}
```

------
#### [ Ruby ]

IAM 用户或 AWS 账户 可以使用 适用于 Ruby 的 AWS SDK 请求临时安全凭证，然后使用这些凭证来访问 Amazon S3。在会话持续时间结束后，这些凭证将过期。

默认情况下，会话的持续时间为一个小时。如果您使用了 IAM 用户凭证，则可在请求临时安全凭证时指定持续时间（15 分钟到角色的最长会话持续时间）。有关临时安全凭证的更多信息，请参阅《IAM 用户指南》**中的[临时安全凭证](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html)。有关发出请求的更多信息，请参阅[提出请求](MakingRequests.md)。

**注意**  
如果您使用AWS 账户 安全凭证获取临时安全凭证，则临时安全凭证的有效期仅为一个小时。只有当您使用 IAM 用户证书来请求会话时，您才可以指定会话持续时间。

以下 Ruby 示例将创建一个临时用户来列出指定存储桶中的项目 1 小时。要使用此示例，则必须具有 AWS 凭证，此类凭证具有创建新的 AWS Security Token Service (AWS STS) 客户端和列出 Amazon S3 存储桶所需的权限。

```
# Prerequisites:
# - A user in AWS Identity and Access Management (IAM). This user must
#   be able to assume the following IAM role. You must run this code example
#   within the context of this user.
# - An existing role in IAM that allows all of the Amazon S3 actions for all of the
#   resources in this code example. This role must also trust the preceding IAM user.
# - An existing S3 bucket.

require 'aws-sdk-core'
require 'aws-sdk-s3'
require 'aws-sdk-iam'

# Checks whether a user exists in IAM.
#
# @param iam [Aws::IAM::Client] An initialized IAM client.
# @param user_name [String] The user's name.
# @return [Boolean] true if the user exists; otherwise, false.
# @example
#   iam_client = Aws::IAM::Client.new(region: 'us-west-2')
#   exit 1 unless user_exists?(iam_client, 'my-user')
def user_exists?(iam_client, user_name)
  response = iam_client.get_user(user_name: user_name)
  return true if response.user.user_name
rescue Aws::IAM::Errors::NoSuchEntity
  # User doesn't exist.
rescue StandardError => e
  puts 'Error while determining whether the user ' \
    "'#{user_name}' exists: #{e.message}"
end

# Creates a user in IAM.
#
# @param iam_client [Aws::IAM::Client] An initialized IAM client.
# @param user_name [String] The user's name.
# @return [AWS:IAM::Types::User] The new user.
# @example
#   iam_client = Aws::IAM::Client.new(region: 'us-west-2')
#   user = create_user(iam_client, 'my-user')
#   exit 1 unless user.user_name
def create_user(iam_client, user_name)
  response = iam_client.create_user(user_name: user_name)
  response.user
rescue StandardError => e
  puts "Error while creating the user '#{user_name}': #{e.message}"
end

# Gets a user in IAM.
#
# @param iam_client [Aws::IAM::Client] An initialized IAM client.
# @param user_name [String] The user's name.
# @return [AWS:IAM::Types::User] The existing user.
# @example
#   iam_client = Aws::IAM::Client.new(region: 'us-west-2')
#   user = get_user(iam_client, 'my-user')
#   exit 1 unless user.user_name
def get_user(iam_client, user_name)
  response = iam_client.get_user(user_name: user_name)
  response.user
rescue StandardError => e
  puts "Error while getting the user '#{user_name}': #{e.message}"
end

# Checks whether a role exists in IAM.
#
# @param iam_client [Aws::IAM::Client] An initialized IAM client.
# @param role_name [String] The role's name.
# @return [Boolean] true if the role exists; otherwise, false.
# @example
#   iam_client = Aws::IAM::Client.new(region: 'us-west-2')
#   exit 1 unless role_exists?(iam_client, 'my-role')
def role_exists?(iam_client, role_name)
  response = iam_client.get_role(role_name: role_name)
  return true if response.role.role_name
rescue StandardError => e
  puts 'Error while determining whether the role ' \
    "'#{role_name}' exists: #{e.message}"
end

# Gets credentials for a role in IAM.
#
# @param sts_client [Aws::STS::Client] An initialized AWS STS client.
# @param role_arn [String] The role's Amazon Resource Name (ARN).
# @param role_session_name [String] A name for this role's session.
# @param duration_seconds [Integer] The number of seconds this session is valid.
# @return [AWS::AssumeRoleCredentials] The credentials.
# @example
#   sts_client = Aws::STS::Client.new(region: 'us-west-2')
#   credentials = get_credentials(
#     sts_client,
#     'arn:aws:iam::123456789012:role/AmazonS3ReadOnly',
#     'ReadAmazonS3Bucket',
#     3600
#   )
#   exit 1 if credentials.nil?
def get_credentials(sts_client, role_arn, role_session_name, duration_seconds)
  Aws::AssumeRoleCredentials.new(
    client: sts_client,
    role_arn: role_arn,
    role_session_name: role_session_name,
    duration_seconds: duration_seconds
  )
rescue StandardError => e
  puts "Error while getting credentials: #{e.message}"
end

# Checks whether a bucket exists in Amazon S3.
#
# @param s3_client [Aws::S3::Client] An initialized Amazon S3 client.
# @param bucket_name [String] The name of the bucket.
# @return [Boolean] true if the bucket exists; otherwise, false.
# @example
#   s3_client = Aws::S3::Client.new(region: 'us-west-2')
#   exit 1 unless bucket_exists?(s3_client, 'amzn-s3-demo-bucket')
def bucket_exists?(s3_client, bucket_name)
  response = s3_client.list_buckets
  response.buckets.each do |bucket|
    return true if bucket.name == bucket_name
  end
rescue StandardError => e
  puts "Error while checking whether the bucket '#{bucket_name}' " \
    "exists: #{e.message}"
end

# Lists the keys and ETags for the objects in an Amazon S3 bucket.
#
# @param s3_client [Aws::S3::Client] An initialized Amazon S3 client.
# @param bucket_name [String] The bucket's name.
# @return [Boolean] true if the objects were listed; otherwise, false.
# @example
#   s3_client = Aws::S3::Client.new(region: 'us-west-2')
#   exit 1 unless list_objects_in_bucket?(s3_client, 'amzn-s3-demo-bucket')
def list_objects_in_bucket?(s3_client, bucket_name)
  puts "Accessing the contents of the bucket named '#{bucket_name}'..."
  response = s3_client.list_objects_v2(
    bucket: bucket_name,
    max_keys: 50
  )

  if response.count.positive?
    puts "Contents of the bucket named '#{bucket_name}' (first 50 objects):"
    puts 'Name => ETag'
    response.contents.each do |obj|
      puts "#{obj.key} => #{obj.etag}"
    end
  else
    puts "No objects in the bucket named '#{bucket_name}'."
  end
  true
rescue StandardError => e
  puts "Error while accessing the bucket named '#{bucket_name}': #{e.message}"
end
```

------