我按照https://docs.aws.amazon.com/AmazonS3/latest/dev/ShareObjectPreSignedURLJavaSDK.html中的示例创建了预签名的s3网址(v4),当我尝试访问已签名的网址时,出现 Access Denied 错误
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>0FB02ECDDF5EAC7B</RequestId>
<HostId>vA+mmsv9PCunNe5uPkPrmpqqN3vFctQ13c9dIRlKWTYsT0zNA1V9g+4YS+lCItrBlyQtdHpyspg=</HostId>
</Error>
以下是代码段
public class GeneratePresignedURL {
public static void main(String[] args) throws IOException {
String clientRegion = "us-east-1";
String bucketName = "com-example-bucket";
String objectKey = "path/to/file.img"; // No leading `/`
// https://com-example-bucket.s3.amazonaws.com/path/to/file.img
try {
AWSCredentialsProvider awsCredentialsProvider = new DefaultAWSCredentialsProviderChain();
// Assuming that us-east-1 defaults to v4, couldn't find a way to set it explicitly
AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
.withRegion(clientRegion)
.withCredentials(awsCredentialsProvider)
.build();
// Set the presigned URL to expire after 10 minutes.
java.util.Date expiration = new java.util.Date();
long expTimeMillis = expiration.getTime();
expTimeMillis += 1000 * 60 * 10;
expiration.setTime(expTimeMillis);
// Generate the presigned URL.
System.out.println("Generating pre-signed URL.");
GeneratePresignedUrlRequest generatePresignedUrlRequest =
new GeneratePresignedUrlRequest(bucketName, objectKey)
.withMethod(HttpMethod.GET)
.withExpiration(expiration);
URL url = s3Client.generatePresignedUrl(generatePresignedUrlRequest);
System.out.println("Pre-Signed URL: " + url.toString());
/*
sample signature:
https://com-example-bucket.s3.amazonaws.com/path/to/file.img?X-Amz-Security-Token=FQoDYXdzEDcaDLjUOdj2hDTZvWUQaiK3AxulqM%2BOPlp%2Bnq71P0LyuI0vj8tT%2F9i24Wd3jY8dUbudWbhUH9IAsPnl7asujO90GlaFP4dXujDDLwIakMjCJSfOFM4IoGJz8XtcjXkqJCNaenbrTA%2F3PfSl%2Fe9wQwJlY8gOu8%2Byioq2ElHULMKv52nEZj8s3v4dD0pGHQTYc4hGV7ty9CYwXNgz6w3TREhxuFdAewNgTRnY1uFNy7on6NDF5IE15vlJ2PxqrX53ZMLKP%2FdU8i5BcpZ3ySVhNpBpU3GJAPMOh%2B2ztCAk1zPjW4G0N5n9BlnjTMGs3vGBb9IW%2F8dzAoxaG9U9%2B%2FCp8euJN562dYYSZ9wmQgsfOVqc5OksdnHVkPJW400ObOcKmc9mqIRyqA%2B3Mv4z0%2Fx6iLYRJ3UaloFSGbmR6VlIxMl%2F67aHrmCnBE23a1%2BNMWgzLx%2FogqZy3CD%2F%2Fs6Jt1qkxUrRwC0RPK93LHD74qm8rjqZcEKFrBOrZsYtcl3zKgRIEHCbatQ7dwT634sdF0MwaD0vwTsbsStZDW903k5C%2FDuz4rEmkPv6c5CmFvxp4xOkUtMbDk4B8Z641CoeAMMOKICH%2FlW7%2F1as3nQo07Ow2QU%3D&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20180621T214222Z&X-Amz-SignedHeaders=host&X-Amz-Expires=3000&X-Amz-Credential=<access_key>%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Signature=<signature>
*/
}
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();
}
}
}
签名格式似乎是正确的,并且我不确定是否缺少其他一些s3客户端配置。 由于没有出现签名不匹配错误或无效的URL错误,因此我认为用于签名URL的访问密钥是正确的。
答案 0 :(得分:1)
以下是生成aws-s3预签名url的步骤,以通过简单的步骤即可通过java创建存储在s3中的内容
<dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-java-sdk-s3</artifactId> <version>1.11.870</version> </dependency>
accessKey, secretKey, region
BasicAWSCredentials awsCreds = new BasicAWSCredentials(accessKey, secretKey); final AmazonS3 s3Client = AmazonS3ClientBuilder.standard().withCredentials(new AWSStaticCredentialsProvider(awsCreds)).withRegion(region).build();
bucketName
// Set the expiry time java.util.Date expiration = new java.util.Date(); long expTimeMillis = expiration.getTime(); expTimeMillis += 1000 * 60 * 60; expiration.setTime(expTimeMillis);
GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName, objecKey) .withMethod(HttpMethod.GET) .withExpiration(expiration); URL url = s3client.generatePresignedUrl(generatePresignedUrlRequest); System.out.println("Pre-Signed URL: " + url.toString());
答案 1 :(得分:0)
这是由于区域不匹配。您已将clientRegion设置为 us-east-1 ,但是如果您从任何其他区域访问它,则会出现拒绝访问错误。您只能从 us-east-1 区域访问该对象,或仅将其更改为您所在的区域。对于印度客户来说是 ap-south-1 。
答案 2 :(得分:0)
问题似乎是该角色无权访问s3存储桶路径/到/文件
答案 3 :(得分:0)
尝试添加 .withPathStyleAccessEnabled(true),如以下快照中所述。
// Assuming that us-east-1 defaults to v4, couldn't find a way to set it explicitly
AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
.withRegion(clientRegion)
.withPathStyleAccessEnabled(true)
.withCredentials(awsCredentialsProvider)
.build();
更改/检查AWS S3存储桶的此更改CROS属性。
<CORSConfiguration>
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
</CORSRule>
</CORSConfiguration>
答案 4 :(得分:0)
请务必为Cognito身份角色分配对S3的访问权限,否则,如果您使用Cognito-credentials用户池会话提供对s3client的必需访问权限,则该权限将被拒绝。这也是我面临的一个问题。