TL;DR
--S3 Presigner added to AWS SDK for Java 2.0 --Supports virtual-hosted style by default --Supports https by default --Changed the expiration date setting method --Use S3 Presigner to generate signed URLs
This article is intended for backends using AWS on Java and Scala, as well as those engaged in SRE operations.
S3 has a mechanism to restrict access to an object by signing the URL it issues to download and upload it.
Prior to AWS SDK for Java 2.10.12, AwsS3V4Signer was used to generate Presigned URLs. Below, the sample code is written in scala.
before.scala
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider
import software.amazon.awssdk.auth.signer.AwsS3V4Signer
import software.amazon.awssdk.auth.signer.params.Aws4PresignerParams
import software.amazon.awssdk.http.{SdkHttpFullRequest, SdkHttpMethod}
val request = SdkHttpFullRequest
.builder()
.encodedPath("bucket/key")
.host("s3.ap-northeast-1.amazonaws.com")
.method(SdkHttpMethod.GET)
.protocol("https")
.build()
val params = Aws4PresignerParams
.builder()
.expirationTime(Instant.now().plusSeconds(300)
.awsCredentials(DefaultCredentialsProvider.create().resolveCredentials())
.signingName("s3")
.signingRegion("ap-northeast-1")
.build()
AwsS3V4Signer.create().presign(request, params).getUri
//Format of the generated signed URL
// https://s3.ap-northeast-1.amazonaws.com/bucket/key?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20200625T000000Z&X-Amz-SignedHeaders=host&X-Amz-Expires=300&X-Amz-Credential=XXX&X-Amz-Signature=YYY
Starting with the AWS SDK for Java 2.10.12, S3 Presigner has been added [^ 1]. You can continue to use Aws S3V4Signer, but it is recommended to use S3 Presigner. The reason for this will be explained later, but on the other hand, AwsS3V4Signer is still used for the internal implementation of S3Presigner.
after.scala
import software.amazon.awssdk.regions.Region
import software.amazon.awssdk.services.s3.model.GetObjectRequest
import software.amazon.awssdk.services.s3.presigner.S3Presigner
import software.amazon.awssdk.services.s3.presigner.model.GetObjectPresignRequest
val presigner: S3Presigner = S3Presigner
.builder()
.region("ap-northeast-1")
.build()
val request = GetObjectRequest
.builder()
.bucket("bucket")
.key("key")
.build()
val presignRequest = GetObjectPresignRequest
.builder()
.signatureDuration(Duration.ofSeconds(300))
.getObjectRequest(request)
.build()
presigner.presignGetObject(presignRequest).url.toURI
//Format of the generated signed URL
// https://bucket.s3.ap-northeast-1.amazonaws.com/key?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20200625T000000Z&X-Amz-SignedHeaders=host&X-Amz-Expires=300&X-Amz-Credential=XXX&X-Amz-Signature=YYY
"https://s3.ap-northeast-1.amazonaws.com/bucket/key" //Before: path style
"https://bucket.s3.ap-northeast-1.amazonaws.com/key" //rear: virtual-hosted style
See below for the differences between the two.
val request = SdkHttpFullRequest
.builder()
.encodedPath("key")
.host("bucket.s3.ap-northeast-1.amazonaws.com")
.method(SdkHttpMethod.GET)
.protocol("https")
.build()
In addition, AwsS3V4Signer can also generate a virtual-hosted style signed URL by setting SdkHttpFullRequest as above, but S3Presigner does not need to be aware of the implementation method.
In AwsS3V4Signer, you can specify the protocol as shown in the .protocol ("https")
part. However, S3Presigner does not have a method to specify the protocol. This is due to the fact that https is specified internally by default. It's hard to imagine the scene to use, but you can also select http by overwriting the endpoint as shown below.
val presigner: S3Presigner = S3Presigner
.builder()
.region("ap-northeast-1")
.endpointOverride(new URI("http://s3.ap-northeast-1.amazonaws.com"))
.build()
In AwsS3V4Signer, it was a way to specify a future date and time that you want to set as an expiration date. However, S3 Presigner uses a method of specifying the validity period as Duration.
//Before
val params = Aws4PresignerParams
.builder()
.expirationTime(Instant.now().plusSeconds(300)
//rear
val presignRequest = GetObjectPresignRequest
.builder()
.signatureDuration(Duration.ofSeconds(300))
[Amazon S3 path-style will be deprecated – and the story ahead –](https://aws.amazon.com/jp/blogs/news/amazon-s3-path-deprecation-plan-the-rest-of-the- story /)
AWS has announced that it will not support path style for buckets created after September 30, 2020. Therefore, it can be said that changes to S3 Presigner need to be dealt with early.
[^ 1]: For details on how to add it, click here [https://github.com/aws/aws-sdk-java-v2/issues/203)