即使输入了错误的访问密钥或秘密密钥,也从 s3 获取 preSignedUrl
Getting preSignedUrl from s3 even if wrong access key or secret key is entered
我正在生成一个 preSignedUrl,然后通过该 url 上传文件。
问题是,即使我输入了错误的访问密钥或秘密密钥,我也会得到 preSignedUrl,但如果我尝试使用那个 url 上传,我会收到 400 错误。
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>AuthorizationQueryParametersError</Code>
<Message>Query-string authentication version 4 requires the X-Amz-Algorithm, X-Amz-Credential, X-Amz-Signature, X-Amz-Date, X-Amz-SignedHeaders, and X-Amz-Expires parameters.</Message>
<RequestId>{requestId}</RequestId>
<HostId>{hostId}</HostId>
</Error>
有什么方法可以让我在生成 preSignedUrl 时遇到错误,这样我就不必尝试上传文件了。
AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("accessKey", "secretKey")))
.withRegion(clientRegion)
.build();
GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName, objectKey)
.withMethod(HttpMethod.PUT)
.withExpiration(expiration);
URL url = s3Client.generatePresignedUrl(generatePresignedUrlRequest);
生成 pre-signed URL 不需要 API 调用;它可以由框架使用指定的访问密钥和秘密生成。
生成的 URL 将在收到请求时由 S3 验证,并且显然只有在使用有效凭据生成它时才会被接受。
底线:为了验证您的凭据,您需要发出 API 实际执行对 AWS 调用的请求。这几乎可以是您的 s3Client 上的任何其他方法。
让我们从这里开始:
.withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("accessKey", "secretKey")))
静态凭据违背 AWS best practice。相反,依赖于通过环境变量或执行角色提供的凭据(当 运行 在 EC2、ECS 或 Lambda 上时)。
验证凭据是否有效的唯一方法是尝试它们。您可以编写一个小的虚拟文件,但是由于 S3 上的最终一致性,这可能会导致任何应该读取该文件的问题。
还有一个问题是,您给 URL 的过期时间可能与凭据的有效期不一致。
所有这些问题的最佳解决方案是创建一个角色,该角色可以访问 S3 上的 PUT 文件,并且持续时间与您的 URL 到期时间一致(注意最长为 12 小时) ,然后显式承担该角色以构建请求:
final String assumedRoleArn = "arn:aws:iam::123456789012:role/Example";
final String sessionName = "example";
final String bucketName = "com-example-mybucket";
final String objectKey = "myfile.txt";
final int expirationSeconds = 12 * 3600;
final Date expiresAt = new Date(System.currentTimeMillis() + expirationSeconds * 1000);
AWSSecurityTokenService stsClient = AWSSecurityTokenServiceClientBuilder.defaultClient();
AWSCredentialsProvider credentialsProvider = new STSAssumeRoleSessionCredentialsProvider.Builder(assumedRoleArn, sessionName)
.withStsClient(stsClient)
.withRoleSessionDurationSeconds(expirationSeconds)
.build();
AmazonS3 s3Client = AmazonS3ClientBuilder.standard().withCredentials(credentialsProvider).build();
URL presignedUrl = s3Client.generatePresignedUrl(bucketName, objectKey, expiresAt, HttpMethod.PUT);
我正在生成一个 preSignedUrl,然后通过该 url 上传文件。 问题是,即使我输入了错误的访问密钥或秘密密钥,我也会得到 preSignedUrl,但如果我尝试使用那个 url 上传,我会收到 400 错误。
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>AuthorizationQueryParametersError</Code>
<Message>Query-string authentication version 4 requires the X-Amz-Algorithm, X-Amz-Credential, X-Amz-Signature, X-Amz-Date, X-Amz-SignedHeaders, and X-Amz-Expires parameters.</Message>
<RequestId>{requestId}</RequestId>
<HostId>{hostId}</HostId>
</Error>
有什么方法可以让我在生成 preSignedUrl 时遇到错误,这样我就不必尝试上传文件了。
AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("accessKey", "secretKey")))
.withRegion(clientRegion)
.build();
GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName, objectKey)
.withMethod(HttpMethod.PUT)
.withExpiration(expiration);
URL url = s3Client.generatePresignedUrl(generatePresignedUrlRequest);
生成 pre-signed URL 不需要 API 调用;它可以由框架使用指定的访问密钥和秘密生成。
生成的 URL 将在收到请求时由 S3 验证,并且显然只有在使用有效凭据生成它时才会被接受。
底线:为了验证您的凭据,您需要发出 API 实际执行对 AWS 调用的请求。这几乎可以是您的 s3Client 上的任何其他方法。
让我们从这里开始:
.withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("accessKey", "secretKey")))
静态凭据违背 AWS best practice。相反,依赖于通过环境变量或执行角色提供的凭据(当 运行 在 EC2、ECS 或 Lambda 上时)。
验证凭据是否有效的唯一方法是尝试它们。您可以编写一个小的虚拟文件,但是由于 S3 上的最终一致性,这可能会导致任何应该读取该文件的问题。
还有一个问题是,您给 URL 的过期时间可能与凭据的有效期不一致。
所有这些问题的最佳解决方案是创建一个角色,该角色可以访问 S3 上的 PUT 文件,并且持续时间与您的 URL 到期时间一致(注意最长为 12 小时) ,然后显式承担该角色以构建请求:
final String assumedRoleArn = "arn:aws:iam::123456789012:role/Example";
final String sessionName = "example";
final String bucketName = "com-example-mybucket";
final String objectKey = "myfile.txt";
final int expirationSeconds = 12 * 3600;
final Date expiresAt = new Date(System.currentTimeMillis() + expirationSeconds * 1000);
AWSSecurityTokenService stsClient = AWSSecurityTokenServiceClientBuilder.defaultClient();
AWSCredentialsProvider credentialsProvider = new STSAssumeRoleSessionCredentialsProvider.Builder(assumedRoleArn, sessionName)
.withStsClient(stsClient)
.withRoleSessionDurationSeconds(expirationSeconds)
.build();
AmazonS3 s3Client = AmazonS3ClientBuilder.standard().withCredentials(credentialsProvider).build();
URL presignedUrl = s3Client.generatePresignedUrl(bucketName, objectKey, expiresAt, HttpMethod.PUT);