Spring Boot亚马逊AWS S3存储桶文件下载 – 访问被拒绝

我有一个自动配置的AWS,Spring Boot应用程序,我正在尝试设置一个端点,只需从Amazon S3中的给定存储桶下载特定文件。 我使用AWS控制台从我的计算机上将一个JPEG文件上传到存储桶中 – 现在我正在尝试使用我的Spring Boot API下载该文件。

我收到以下错误: com.amazonaws.services.s3.model.AmazonS3Exception: Access Denied (Service: Amazon S3; Status Code: 403; Error Code: AccessDenied;

我在AWS控制台上创建了一个用户和一个组(用户在组中); 用户/组具有S3的完全访问权限以及管理员访问权限。 我下载了访问密钥/密钥对,出于测试目的,将密钥直接粘贴到我的application.properties文件中,如下所示(此处未显示密钥,显然:))。

我很困惑为什么我仍然被拒绝访问。 我一直在寻找和研究这个问题; 我似乎无法找到特定于Spring Boot的此问题的解决方案。 任何帮助将不胜感激。

application.properties:

 cloud.aws.credentials.accessKey=myaccesskey cloud.aws.credentials.secretKey=mysecretkey cloud.aws.credentials.instanceProfile=false cloud.aws.stack.auto=false cloud.aws.region.auto=true cloud.aws.region.static=myregion 

SimpleResourceLoadingBean.java:

 @RestController public class SimpleResourceLoadingBean { private static Logger log = LoggerFactory.getLogger(HealthMonitorApplication.class); @Autowired private ResourceLoader resourceLoader; @RequestMapping("/getresource") public String resourceLoadingMethod() throws IOException { log.info("IN RESOURCE LOADER"); Resource resource = this.resourceLoader.getResource("s3://s3.amazonaws.com/mybucket/myfile.ext"); InputStream inputStream = resource.getInputStream(); return inputStream.toString(); } } 

pom.xml(只是与问题相关的依赖项)

   org.springframework.cloud spring-cloud-starter-aws 1.1.0.RELEASE   org.springframework.cloud spring-cloud-aws-autoconfigure 1.1.0.RELEASE  

找出解决方案。 除了application.properties配置之外,我还必须创建一个配置类,以便在提供适当的凭据时允许我访问AmazonS3Client对象。 我在GitHub上关注了这个例子:

https://github.com/brant-hwang/spring-cloud-aws-example/blob/master/src/main/java/com/axisj/spring/cloud/aws/AWSConfiguration.java

AWSConfiguration.java:

 import com.amazonaws.auth.AWSCredentials; import com.amazonaws.auth.BasicAWSCredentials; import com.amazonaws.regions.Region; import com.amazonaws.regions.Regions; import com.amazonaws.services.s3.AmazonS3Client; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class AWSConfiguration { @Value("${cloud.aws.credentials.accessKey}") private String accessKey; @Value("${cloud.aws.credentials.secretKey}") private String secretKey; @Value("${cloud.aws.region}") private String region; @Bean public BasicAWSCredentials basicAWSCredentials() { return new BasicAWSCredentials(accessKey, secretKey); } @Bean public AmazonS3Client amazonS3Client(AWSCredentials awsCredentials) { AmazonS3Client amazonS3Client = new AmazonS3Client(awsCredentials); amazonS3Client.setRegion(Region.getRegion(Regions.fromName(region))); return amazonS3Client; } } 

配置完成后,您可以在其他类中创建AmazonS3Client对象(自动assembly),并使用客户端向S3云发出请求。 该示例使用包装类作为服务,以便简化其他控制器类的实现。

S3Wrapper.java:

 import com.amazonaws.services.s3.AmazonS3Client; import com.amazonaws.services.s3.model.*; import org.apache.commons.io.IOUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import org.springframework.web.multipart.MultipartFile; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.URLEncoder; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @Service public class S3Wrapper { @Autowired private AmazonS3Client amazonS3Client; @Value("${cloud.aws.s3.bucket}") private String bucket; private PutObjectResult upload(String filePath, String uploadKey) throws FileNotFoundException { return upload(new FileInputStream(filePath), uploadKey); } private PutObjectResult upload(InputStream inputStream, String uploadKey) { PutObjectRequest putObjectRequest = new PutObjectRequest(bucket, uploadKey, inputStream, new ObjectMetadata()); putObjectRequest.setCannedAcl(CannedAccessControlList.PublicRead); PutObjectResult putObjectResult = amazonS3Client.putObject(putObjectRequest); IOUtils.closeQuietly(inputStream); return putObjectResult; } public List upload(MultipartFile[] multipartFiles) { List putObjectResults = new ArrayList<>(); Arrays.stream(multipartFiles) .filter(multipartFile -> !StringUtils.isEmpty(multipartFile.getOriginalFilename())) .forEach(multipartFile -> { try { putObjectResults.add(upload(multipartFile.getInputStream(), multipartFile.getOriginalFilename())); } catch (IOException e) { e.printStackTrace(); } }); return putObjectResults; } public ResponseEntity download(String key) throws IOException { GetObjectRequest getObjectRequest = new GetObjectRequest(bucket, key); S3Object s3Object = amazonS3Client.getObject(getObjectRequest); S3ObjectInputStream objectInputStream = s3Object.getObjectContent(); byte[] bytes = IOUtils.toByteArray(objectInputStream); String fileName = URLEncoder.encode(key, "UTF-8").replaceAll("\\+", "%20"); HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM); httpHeaders.setContentLength(bytes.length); httpHeaders.setContentDispositionFormData("attachment", fileName); return new ResponseEntity<>(bytes, httpHeaders, HttpStatus.OK); } public List list() { ObjectListing objectListing = amazonS3Client.listObjects(new ListObjectsRequest().withBucketName(bucket)); List s3ObjectSummaries = objectListing.getObjectSummaries(); return s3ObjectSummaries; } } 

注意:为了使用Apache Commons IO库,需要将以下依赖项添加到pom.xml中。

pom.xml中:

  org.apache.commons commons-io 1.3.2  

接受的答案是使用已弃用的API。 这是一个更新的版本。

首先,更新您的maven依赖项:

   com.amazonaws aws-java-sdk 1.11.274  

AWSConfiguration.java

 import com.amazonaws.auth.AWSCredentials; import com.amazonaws.auth.AWSStaticCredentialsProvider; import com.amazonaws.auth.BasicAWSCredentials; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3ClientBuilder; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class AWSConfiguration { @Value("${cloud.aws.credentials.accessKey}") private String accessKey; @Value("${cloud.aws.credentials.secretKey}") private String secretKey; @Value("${cloud.aws.region}") private String region; @Bean public BasicAWSCredentials basicAWSCredentials() { return new BasicAWSCredentials(accessKey, secretKey); } @Bean public AmazonS3 amazonS3Client(AWSCredentials awsCredentials) { AmazonS3ClientBuilder builder = AmazonS3ClientBuilder.standard(); builder.withCredentials(new AWSStaticCredentialsProvider(awsCredentials)); builder.setRegion(region); AmazonS3 amazonS3 = builder.build(); return amazonS3; } } 

S3Service.java

 import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3Client; import com.amazonaws.services.s3.model.*; import org.apache.commons.io.IOUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import org.springframework.web.multipart.MultipartFile; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.URLEncoder; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @Service public class S3Service { @Autowired private AmazonS3 amazonS3; @Value("${cloud.aws.s3.bucket}") private String bucket; private PutObjectResult upload(String filePath, String uploadKey) throws FileNotFoundException { return upload(new FileInputStream(filePath), uploadKey); } private PutObjectResult upload(InputStream inputStream, String uploadKey) { PutObjectRequest putObjectRequest = new PutObjectRequest(bucket, uploadKey, inputStream, new ObjectMetadata()); putObjectRequest.setCannedAcl(CannedAccessControlList.PublicRead); PutObjectResult putObjectResult = amazonS3.putObject(putObjectRequest); IOUtils.closeQuietly(inputStream); return putObjectResult; } public List upload(MultipartFile[] multipartFiles) { List putObjectResults = new ArrayList<>(); Arrays.stream(multipartFiles) .filter(multipartFile -> !StringUtils.isEmpty(multipartFile.getOriginalFilename())) .forEach(multipartFile -> { try { putObjectResults.add(upload(multipartFile.getInputStream(), multipartFile.getOriginalFilename())); } catch (IOException e) { e.printStackTrace(); } }); return putObjectResults; } public ResponseEntity download(String key) throws IOException { GetObjectRequest getObjectRequest = new GetObjectRequest(bucket, key); S3Object s3Object = amazonS3.getObject(getObjectRequest); S3ObjectInputStream objectInputStream = s3Object.getObjectContent(); byte[] bytes = IOUtils.toByteArray(objectInputStream); String fileName = URLEncoder.encode(key, "UTF-8").replaceAll("\\+", "%20"); HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM); httpHeaders.setContentLength(bytes.length); httpHeaders.setContentDispositionFormData("attachment", fileName); return new ResponseEntity<>(bytes, httpHeaders, HttpStatus.OK); } public List list() { ObjectListing objectListing = amazonS3.listObjects(new ListObjectsRequest().withBucketName(bucket)); List s3ObjectSummaries = objectListing.getObjectSummaries(); return s3ObjectSummaries; } } 
Interesting Posts