翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。
署名 Amazon S3 付き URLsの使用
署名付き URLs は、ユーザーが AWS 認証情報やアクセス許可を持つことなく、プライベート S3 オブジェクトへの一時的なアクセスを提供します。
たとえば、Alice に S3 オブジェクトへのアクセス権限があり、そのオブジェクトへのアクセス権限を一時的に Bob と共有するとします。Alice は、署名付き Get リクエストを生成して Bob との共有し、Bob が Alice の認証情報にアクセスすることなくそのオブジェクトをダウンロードできるようにすることができます。HTTP GET リクエストと HTTP PUT リクエスト用の署名付き URL を生成できます。
オブジェクトの署名付き URL を生成して、オブジェクトをダウンロードします (GET リクエスト)。
以下の例は次の 2 つの部分で構成されます。
-
パート 1: Alice はオブジェクトの署名付き URL を生成します。
-
パート 2: Bob は署名済み URL を使用してオブジェクトをダウンロードします。
パート 1: URL を生成する
Alice はすでに S3 バケットにオブジェクトを持っています。彼女は次のコードを使用して、Bob が後続の GET リクエストで使用できる URL 文字列を生成します。
import com.example.s3.util.PresignUrlUtils; import org.slf4j.Logger; import software.amazon.awssdk.http.HttpExecuteRequest; import software.amazon.awssdk.http.HttpExecuteResponse; import software.amazon.awssdk.http.SdkHttpClient; import software.amazon.awssdk.http.SdkHttpMethod; import software.amazon.awssdk.http.SdkHttpRequest; import software.amazon.awssdk.http.apache.ApacheHttpClient; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.model.GetObjectRequest; import software.amazon.awssdk.services.s3.model.S3Exception; import software.amazon.awssdk.services.s3.presigner.S3Presigner; import software.amazon.awssdk.services.s3.presigner.model.GetObjectPresignRequest; import software.amazon.awssdk.services.s3.presigner.model.PresignedGetObjectRequest; import software.amazon.awssdk.utils.IoUtils; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URISyntaxException; import java.net.URL; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.nio.file.Paths; import java.time.Duration; import java.util.UUID;
/* Create a pre-signed URL to download an object in a subsequent GET request. */ public String createPresignedGetUrl(String bucketName, String keyName) { try (S3Presigner presigner = S3Presigner.create()) { GetObjectRequest objectRequest = GetObjectRequest.builder() .bucket(bucketName) .key(keyName) .build(); GetObjectPresignRequest presignRequest = GetObjectPresignRequest.builder() .signatureDuration(Duration.ofMinutes(10)) // The URL will expire in 10 minutes. .getObjectRequest(objectRequest) .build(); PresignedGetObjectRequest presignedRequest = presigner.presignGetObject(presignRequest); logger.info("Presigned URL: [{}]", presignedRequest.url().toString()); logger.info("HTTP method: [{}]", presignedRequest.httpRequest().method()); return presignedRequest.url().toExternalForm(); } }
パート 2: オブジェクトをダウンロードする
Bob は、次のいずれかのコードオプションを使用してオブジェクトをダウンロードします。または、ブラウザを使用して GET リクエストを実行することもできます。
/* Use the JDK HttpURLConnection (since v1.1) class to do the download. */ public byte[] useHttpUrlConnectionToGet(String presignedUrlString) { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); // Capture the response body to a byte array. try { URL presignedUrl = new URL(presignedUrlString); HttpURLConnection connection = (HttpURLConnection) presignedUrl.openConnection(); connection.setRequestMethod("GET"); // Download the result of executing the request. try (InputStream content = connection.getInputStream()) { IoUtils.copy(content, byteArrayOutputStream); } logger.info("HTTP response code is " + connection.getResponseCode()); } catch (S3Exception | IOException e) { logger.error(e.getMessage(), e); } return byteArrayOutputStream.toByteArray(); }
/* Use the JDK HttpClient (since v11) class to do the download. */ public byte[] useHttpClientToGet(String presignedUrlString) { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); // Capture the response body to a byte array. HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(); HttpClient httpClient = HttpClient.newHttpClient(); try { URL presignedUrl = new URL(presignedUrlString); HttpResponse<InputStream> response = httpClient.send(requestBuilder .uri(presignedUrl.toURI()) .GET() .build(), HttpResponse.BodyHandlers.ofInputStream()); IoUtils.copy(response.body(), byteArrayOutputStream); logger.info("HTTP response code is " + response.statusCode()); } catch (URISyntaxException | InterruptedException | IOException e) { logger.error(e.getMessage(), e); } return byteArrayOutputStream.toByteArray(); }
/* Use the AWS SDK for Java SdkHttpClient class to do the download. */ public byte[] useSdkHttpClientToGet(String presignedUrlString) { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); // Capture the response body to a byte array. try { URL presignedUrl = new URL(presignedUrlString); SdkHttpRequest request = SdkHttpRequest.builder() .method(SdkHttpMethod.GET) .uri(presignedUrl.toURI()) .build(); HttpExecuteRequest executeRequest = HttpExecuteRequest.builder() .request(request) .build(); try (SdkHttpClient sdkHttpClient = ApacheHttpClient.create()) { HttpExecuteResponse response = sdkHttpClient.prepareRequest(executeRequest).call(); response.responseBody().ifPresentOrElse( abortableInputStream -> { try { IoUtils.copy(abortableInputStream, byteArrayOutputStream); } catch (IOException e) { throw new RuntimeException(e); } }, () -> logger.error("No response body.")); logger.info("HTTP Response code is {}", response.httpResponse().statusCode()); } } catch (URISyntaxException | IOException e) { logger.error(e.getMessage(), e); } return byteArrayOutputStream.toByteArray(); }
AWS SDK for Java 2.x には、SDK 非同期パイプラインを介して署名付き URL を使用してオブジェクトをダウンロードする署名付き URL 拡張機能S3AsyncClientが に用意されています。を使用して拡張機能にアクセスしますS3AsyncClient.presignedUrlExtension()。この機能は SDK バージョン 2.48.0 以降で使用できます。
CRT クライアントの制限
AWS CRT ベースの S3 クライアント (S3AsyncClient.crtBuilder()) は現在、署名付き URL 拡張をサポートしていません。代わりに S3AsyncClient.builder() を使用します。
チェックサムモードの要件
データの整合性を検証するには、署名付き URL を生成するGetObjectRequestときに checksumMode(ChecksumMode.ENABLED)で を設定します。事前署名時にチェックサムモードを指定します。ダウンロードの実行時に後で追加することはできません。署名S3AsyncClient付き URL 拡張機能を使用すると、SDK は必要なx-amz-checksum-modeヘッダーを自動的に送信します。
import java.nio.file.Paths; import software.amazon.awssdk.core.ResponseBytes; import software.amazon.awssdk.core.async.AsyncResponseTransformer; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.s3.S3AsyncClient; import software.amazon.awssdk.services.s3.model.GetObjectResponse; import software.amazon.awssdk.services.s3.presignedurl.model.PresignedUrlDownloadRequest;
ファイルまたは バイトにダウンロードする
大きなファイルのマルチパートダウンロード
大きなオブジェクトを並行してダウンロードするには、クライアントmultipartEnabled(true)で を設定します。
Amazon S3 Transfer Manager を使用する
Amazon S3 Transfer Manager を使用すると、 を通じて進行状況を追跡する署名付き URLs を使用してオブジェクトをダウンロードできますTransferListener。
s3-transfer-manager アーティファクトをプロジェクトに追加します。
<dependencyManagement> <dependencies> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>bom</artifactId> <version>2.48.01</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>s3-transfer-manager</artifactId> </dependency> </dependencies>
1 Maven Central Repository で最新の BOM バージョンを検索します
import java.nio.file.Paths; import software.amazon.awssdk.core.ResponseBytes; import software.amazon.awssdk.core.async.AsyncResponseTransformer; import software.amazon.awssdk.services.s3.model.GetObjectResponse; import software.amazon.awssdk.services.s3.presignedurl.model.PresignedUrlDownloadRequest; import software.amazon.awssdk.transfer.s3.S3TransferManager; import software.amazon.awssdk.transfer.s3.model.CompletedFileDownload; import software.amazon.awssdk.transfer.s3.model.Download; import software.amazon.awssdk.transfer.s3.model.PresignedDownloadFileRequest; import software.amazon.awssdk.transfer.s3.model.PresignedDownloadRequest; import software.amazon.awssdk.transfer.s3.model.PresignedFileDownload; import software.amazon.awssdk.transfer.s3.progress.LoggingTransferListener;
一時停止と再開はサポートされていません
通常の とは異なりFileDownload、 PresignedFileDownloadは一時停止と再開をサポートしていません。これは、署名付き URLsになる可能性があるためです。
設定オプションや追加の例など、Amazon S3 Transfer Manager の詳細については、「」を参照してくださいAmazon S3 Transfer Manager を使用してファイルとディレクトリを転送する。
アップロード用の署名付き URL を生成して、ファイルをアップロードします (PUT リクエスト)。
以下の例は次の 2 つの部分で構成されます。
-
パート 1: Alice はオブジェクトをアップロードするために署名付き URL を生成します。
-
パート 2: Bob は署名済み URL を使用してファイルをアップロードします。
パート 1: URL を生成する
Alice はすでに S3 バケットを持っています。彼女は次のコードを使用して、Bob が後続の PUT リクエストで使用できる URL 文字列を生成します。
import com.example.s3.util.PresignUrlUtils; import org.slf4j.Logger; import software.amazon.awssdk.core.internal.sync.FileContentStreamProvider; import software.amazon.awssdk.http.HttpExecuteRequest; import software.amazon.awssdk.http.HttpExecuteResponse; import software.amazon.awssdk.http.SdkHttpClient; import software.amazon.awssdk.http.SdkHttpMethod; import software.amazon.awssdk.http.SdkHttpRequest; import software.amazon.awssdk.http.apache.ApacheHttpClient; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.model.PutObjectRequest; import software.amazon.awssdk.services.s3.model.S3Exception; import software.amazon.awssdk.services.s3.presigner.S3Presigner; import software.amazon.awssdk.services.s3.presigner.model.PresignedPutObjectRequest; import software.amazon.awssdk.services.s3.presigner.model.PutObjectPresignRequest; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URISyntaxException; import java.net.URL; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.file.Path; import java.nio.file.Paths; import java.time.Duration; import java.util.Map; import java.util.UUID;
/* Create a presigned URL to use in a subsequent PUT request */ public String createPresignedUrl(String bucketName, String keyName, Map<String, String> metadata) { try (S3Presigner presigner = S3Presigner.create()) { PutObjectRequest objectRequest = PutObjectRequest.builder() .bucket(bucketName) .key(keyName) .metadata(metadata) .build(); PutObjectPresignRequest presignRequest = PutObjectPresignRequest.builder() .signatureDuration(Duration.ofMinutes(10)) // The URL expires in 10 minutes. .putObjectRequest(objectRequest) .build(); PresignedPutObjectRequest presignedRequest = presigner.presignPutObject(presignRequest); String myURL = presignedRequest.url().toString(); logger.info("Presigned URL to upload a file to: [{}]", myURL); logger.info("HTTP method: [{}]", presignedRequest.httpRequest().method()); return presignedRequest.url().toExternalForm(); } }
パート 2: ファイルオブジェクトをアップロードする
ボブは次の 3 つのコードオプションのいずれかを使用してファイルをアップロードします。
/* Use the JDK HttpURLConnection (since v1.1) class to do the upload. */ public void useHttpUrlConnectionToPut(String presignedUrlString, File fileToPut, Map<String, String> metadata) { logger.info("Begin [{}] upload", fileToPut.toString()); try { URL presignedUrl = new URL(presignedUrlString); HttpURLConnection connection = (HttpURLConnection) presignedUrl.openConnection(); connection.setDoOutput(true); metadata.forEach((k, v) -> connection.setRequestProperty("x-amz-meta-" + k, v)); connection.setRequestMethod("PUT"); OutputStream out = connection.getOutputStream(); try (RandomAccessFile file = new RandomAccessFile(fileToPut, "r"); FileChannel inChannel = file.getChannel()) { ByteBuffer buffer = ByteBuffer.allocate(8192); //Buffer size is 8k while (inChannel.read(buffer) > 0) { buffer.flip(); for (int i = 0; i < buffer.limit(); i++) { out.write(buffer.get()); } buffer.clear(); } } catch (IOException e) { logger.error(e.getMessage(), e); } out.close(); connection.getResponseCode(); logger.info("HTTP response code is " + connection.getResponseCode()); } catch (S3Exception | IOException e) { logger.error(e.getMessage(), e); } }
/* Use the JDK HttpClient (since v11) class to do the upload. */ public void useHttpClientToPut(String presignedUrlString, File fileToPut, Map<String, String> metadata) { logger.info("Begin [{}] upload", fileToPut.toString()); HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(); metadata.forEach((k, v) -> requestBuilder.header("x-amz-meta-" + k, v)); HttpClient httpClient = HttpClient.newHttpClient(); try { final HttpResponse<Void> response = httpClient.send(requestBuilder .uri(new URL(presignedUrlString).toURI()) .PUT(HttpRequest.BodyPublishers.ofFile(Path.of(fileToPut.toURI()))) .build(), HttpResponse.BodyHandlers.discarding()); logger.info("HTTP response code is " + response.statusCode()); } catch (URISyntaxException | InterruptedException | IOException e) { logger.error(e.getMessage(), e); } }
/* Use the AWS SDK for Java V2 SdkHttpClient class to do the upload. */ public void useSdkHttpClientToPut(String presignedUrlString, File fileToPut, Map<String, String> metadata) { logger.info("Begin [{}] upload", fileToPut.toString()); try { URL presignedUrl = new URL(presignedUrlString); SdkHttpRequest.Builder requestBuilder = SdkHttpRequest.builder() .method(SdkHttpMethod.PUT) .uri(presignedUrl.toURI()); // Add headers metadata.forEach((k, v) -> requestBuilder.putHeader("x-amz-meta-" + k, v)); // Finish building the request. SdkHttpRequest request = requestBuilder.build(); HttpExecuteRequest executeRequest = HttpExecuteRequest.builder() .request(request) .contentStreamProvider(new FileContentStreamProvider(fileToPut.toPath())) .build(); try (SdkHttpClient sdkHttpClient = ApacheHttpClient.create()) { HttpExecuteResponse response = sdkHttpClient.prepareRequest(executeRequest).call(); logger.info("Response code: {}", response.httpResponse().statusCode()); } } catch (URISyntaxException | IOException e) { logger.error(e.getMessage(), e); } }
リクエストフィールドを URL クエリパラメータとして含める
GetObjectRequestrequestPayer、、serverSideEncryption、、 acl metadataは x-amz-*ヘッダーにstorageClassマッピングされます。これらのフィールドのいずれかを設定するリクエストに事前署名すると、署名はヘッダーをカバーします。ただし、S3Presigner
署名付き URL の呼び出し元は、リクエストで同じx-amz-*ヘッダーを送信する必要があります。それ以外の場合、Amazon S3 は を返しますSignatureDoesNotMatch。カスタムヘッダーを設定できる HTTP クライアントは、それらのヘッダーを直接送信します。たとえば、前述の HttpURLConnection、HttpClient、および SdkHttpClient
余分なヘッダーなしで URL を機能させるには、型付きフィールドを設定する代わりに、値を署名付きクエリパラメータとして渡します。AwsRequestOverrideConfiguration
リクエスタ支払いを使用して GET リクエストに事前署名する
次の の例では、リクエスタ支払い設定GetObjectRequestを使用して の署名付き URL を生成します。値はクエリパラメータであるため、呼び出し元は x-amz-request-payerヘッダーを送信せずに URL を使用できます。
try (S3Presigner presigner = S3Presigner.create()) { GetObjectRequest getObjectRequest = GetObjectRequest.builder() .bucket("amzn-s3-demo-bucket") .key("example-key") .overrideConfiguration(o -> o.putRawQueryParameter("x-amz-request-payer", "requester")) .build(); GetObjectPresignRequest presignRequest = GetObjectPresignRequest.builder() .signatureDuration(Duration.ofMinutes(10)) .getObjectRequest(getObjectRequest) .build(); PresignedGetObjectRequest presigned = presigner.presignGetObject(presignRequest); logger.info("Pre-signed URL: [{}]", presigned.url()); // Confirm the URL requires no headers at request time: logger.info("Signed headers: {}", presigned.signedHeaders().keySet()); // [host] }
メタデータを使用して PUT リクエストに事前署名する
次の例では、署名付きクエリパラメータとして 2 つのメタデータ値PutObjectRequestを持つ の署名付き URL を生成します。値はクエリパラメータであるため、どの発信者もx-amz-meta-*ヘッダーを送信せずに URL を使用できます。
try (S3Presigner presigner = S3Presigner.create()) { PutObjectRequest putObjectRequest = PutObjectRequest.builder() .bucket("amzn-s3-demo-bucket") .key("example-key") .overrideConfiguration(o -> o .putRawQueryParameter("x-amz-meta-author", "alice") .putRawQueryParameter("x-amz-meta-purpose", "demo")) .build(); PutObjectPresignRequest presignRequest = PutObjectPresignRequest.builder() .signatureDuration(Duration.ofMinutes(10)) .putObjectRequest(putObjectRequest) .build(); PresignedPutObjectRequest presigned = presigner.presignPutObject(presignRequest); logger.info("Pre-signed URL: [{}]", presigned.url()); // Confirm the URL requires no headers at upload time: logger.info("Signed headers: {}", presigned.signedHeaders().keySet()); // [host] }
PUT リクエストに事前署名してファイルをアップロードする
次の例は、ワークフロー全体を示しています。マップとして指定したx-amz-*名前と値を使用して PUT リクエストに事前署名するメソッドと、 を使用してファイルをアップロードするメソッドですSdkHttpClient。値は既に署名付き URL の一部であるため、アップロードメソッドはx-amz-*ヘッダーを設定しません。対照的に、前のアップロード例ではx-amz-meta-*ヘッダーを明示的に設定しています。
import com.example.s3.util.PresignUrlUtils; import org.slf4j.Logger; import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration; import software.amazon.awssdk.core.internal.sync.FileContentStreamProvider; import software.amazon.awssdk.http.HttpExecuteRequest; import software.amazon.awssdk.http.HttpExecuteResponse; import software.amazon.awssdk.http.SdkHttpClient; import software.amazon.awssdk.http.SdkHttpMethod; import software.amazon.awssdk.http.SdkHttpRequest; import software.amazon.awssdk.http.apache.ApacheHttpClient; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.model.PutObjectRequest; import software.amazon.awssdk.services.s3.presigner.S3Presigner; import software.amazon.awssdk.services.s3.presigner.model.PresignedPutObjectRequest; import software.amazon.awssdk.services.s3.presigner.model.PutObjectPresignRequest; import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.net.URL; import java.nio.file.Paths; import java.time.Duration; import java.util.Map; import java.util.UUID;
URL を生成する。
/** * Creates a presigned URL to use in a subsequent HTTP PUT request. The code adds query parameters * to the request instead of using headers. By using query parameters, you do not need to add the * the parameters as headers when the PUT request is eventually sent. * * @param bucketName Bucket name where the object will be uploaded. * @param keyName Key name of the object that will be uploaded. * @param queryParams Query string parameters to be added to the presigned URL. * @return */ public String createPresignedUrl(String bucketName, String keyName, Map<String, String> queryParams) { try (S3Presigner presigner = S3Presigner.create()) { // Create an override configuration to store the query parameters. AwsRequestOverrideConfiguration.Builder overrideConfigurationBuilder = AwsRequestOverrideConfiguration.builder(); queryParams.forEach(overrideConfigurationBuilder::putRawQueryParameter); PutObjectRequest objectRequest = PutObjectRequest.builder() .bucket(bucketName) .key(keyName) .overrideConfiguration(overrideConfigurationBuilder.build()) // Add the override configuration. .build(); PutObjectPresignRequest presignRequest = PutObjectPresignRequest.builder() .signatureDuration(Duration.ofMinutes(10)) // The URL expires in 10 minutes. .putObjectRequest(objectRequest) .build(); PresignedPutObjectRequest presignedRequest = presigner.presignPutObject(presignRequest); String myURL = presignedRequest.url().toString(); logger.info("Presigned URL to upload a file to: [{}]", myURL); logger.info("HTTP method: [{}]", presignedRequest.httpRequest().method()); return presignedRequest.url().toExternalForm(); } }
でファイルをアップロードしますSdkHttpClient。
/** * Use the AWS SDK for Java V2 SdkHttpClient class to execute the PUT request. Since the * URL contains the query parameters, no headers are needed for metadata, SSE settings, or ACL settings. * * @param presignedUrlString The URL for the PUT request. * @param fileToPut File to uplaod */ public void useSdkHttpClientToPut(String presignedUrlString, File fileToPut) { logger.info("Begin [{}] upload", fileToPut.toString()); try { URL presignedUrl = new URL(presignedUrlString); SdkHttpRequest.Builder requestBuilder = SdkHttpRequest.builder() .method(SdkHttpMethod.PUT) .uri(presignedUrl.toURI()); SdkHttpRequest request = requestBuilder.build(); HttpExecuteRequest executeRequest = HttpExecuteRequest.builder() .request(request) .contentStreamProvider(new FileContentStreamProvider(fileToPut.toPath())) .build(); try (SdkHttpClient sdkHttpClient = ApacheHttpClient.create()) { HttpExecuteResponse response = sdkHttpClient.prepareRequest(executeRequest).call(); logger.info("Response code: {}", response.httpResponse().statusCode()); } } catch (URISyntaxException | IOException e) { logger.error(e.getMessage(), e); } }
署名付きリクエストに必要なヘッダーを確認する
発信者が送信する必要がある特定の署名付きリクエストのヘッダーを確認するには、返された PresignedRequestx-amz-*の名前は、発信者が送信する必要があるヘッダーです。要件からヘッダーを削除する場合は、型付きフィールドを設定するputRawQueryParameter代わりに、その値を に渡します。