java - 如何使用 java 和 AWS 临时凭证从 s3 存储桶下载文件

标签 java amazon-web-services amazon-s3 aws-lambda

我有这段代码可以将文件从 s3 存储桶下载到 lambda 服务器的 tmp 空间。

String url = "https://slack-automation.s3.amazonaws.com/slack.xlsx";

URL link = new URL(url);

/* //AmazonS3 s3Client = new AmazonS3Client(new ProfileCredentialsProvider());
   AmazonS3 s3Client = AmazonS3ClientBuilder.standard().build() ;
   S3Object object = s3Client.getObject(new GetObjectRequest(bucketName, key));
   InputStream objectData = object.getObjectContent();
   // Process the objectData stream.
   objectData.close();
 */

// Code to download
InputStream in = new BufferedInputStream(link.openStream());
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int n = 0;

while (-1 != (n = in.read(buf))) {
    out.write(buf, 0, n);
}

out.close();
in.close();
byte[] response = out.toByteArray();

FileOutputStream fos = new FileOutputStream("/tmp/" + fileName);
fos.write(response);
fos.close();
file = new File("/tmp/" + fileName);

//file = new File(filePath);
inputStream = new FileInputStream(file);
workBook = new XSSFWorkbook(inputStream);
workBookSheet = workBook.getSheet(workBook.getSheetName(0));
rowCount = workBookSheet.getPhysicalNumberOfRows();
formatter = new DataFormatter();

但问题是要访问这个文件,必须给予公共(public)权限。

如何通过获取此处给出的临时凭据来将此文件下载到 lambda 服务器临时空间:https://docs.aws.amazon.com/AmazonS3/latest/dev/AuthUsingTempSessionTokenJava.html

我无法实现,有人可以帮助我使用临时凭据下载文件的代码,而无需像上面提到的方法那样传递我的访问 key 和 secret key 吗?

谢谢 Akshay Sing,我不知道如何用代码进行评论,我在你的回答后尝试的代码在这里

public void setupWorkbook(String filePath) 抛出 IOException {

    String clientRegion = "eu-central-1";
    String roleARN = "myAwsArnRoleOverHere";
    String roleSessionName = "slackautomation";
    String bucketName = "slack-automation";
    String key = "slack.xlsx";


    String fileName = "slack.xlsx";



    try {

        AWSSecurityTokenService stsClient = AWSSecurityTokenServiceClientBuilder.standard()
                                                .withCredentials(new ProfileCredentialsProvider())
                                                .withRegion(clientRegion)
                                                .build();

        AssumeRoleRequest roleRequest = new AssumeRoleRequest()
                                                .withRoleArn(roleARN)
                                                .withRoleSessionName(roleSessionName);
        stsClient.assumeRole(roleRequest);

        // Start a session.
        GetSessionTokenRequest getSessionTokenRequest = new GetSessionTokenRequest();
        // The duration can be set to more than 3600 seconds only if temporary
        // credentials are requested by an IAM user rather than an account owner.
        getSessionTokenRequest.setDurationSeconds(900);
        GetSessionTokenResult sessionTokenResult = stsClient.getSessionToken(getSessionTokenRequest);
        Credentials sessionCredentials = sessionTokenResult.getCredentials();

        // Package the temporary security credentials as a BasicSessionCredentials object 
        // for an Amazon S3 client object to use.
        BasicSessionCredentials basicSessionCredentials = new BasicSessionCredentials(
                sessionCredentials.getAccessKeyId(), sessionCredentials.getSecretAccessKey(),
                sessionCredentials.getSessionToken());

        // Provide temporary security credentials so that the Amazon S3 client 
        // can send authenticated requests to Amazon S3. You create the client 
        // using the basicSessionCredentials object.
        AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
                                .withCredentials(new AWSStaticCredentialsProvider(basicSessionCredentials))
                                .withRegion(clientRegion)
                                .build();

        // Verify that assuming the role worked and the permissions are set correctly
        // by getting a set of object keys from the bucket.
        ObjectListing objects = s3Client.listObjects(bucketName);

        System.out.println("No. of Objects: " + objects.getObjectSummaries().size());
        S3Object fileObject = s3Client.getObject(new GetObjectRequest(bucketName, key));         
        InputStream in = new BufferedInputStream(fileObject.getObjectContent());

        ByteArrayOutputStream out = new ByteArrayOutputStream();

        byte[] buf = new byte[1024];

        int n = 0;

        while (-1 != (n = in.read(buf))) {

            out.write(buf, 0, n);

        }

        out.close();
        in.close();
        byte[] response = out.toByteArray();
        FileOutputStream fos = new FileOutputStream("/tmp/" + fileName);

        fos.write(response);

        fos.close();
        file = new File("/tmp/" + fileName);

        //file = new File(filePath);

        inputStream = new FileInputStream(file);

        workBook = new XSSFWorkbook(inputStream);

        workBookSheet = workBook.getSheet(workBook.getSheetName(0));

        rowCount = workBookSheet.getPhysicalNumberOfRows();

        formatter = new DataFormatter();


    }
    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();
    }

但它不起作用,它在“stsClient.assumeRole(roleRequest);”上抛出错误

只有行号的错误,没有太多线索。

最佳答案

我目前正在使用以下过程从我的 S3 存储桶下载图像并存储它们以将图像的 zip 返回给用户。我为您排除了 zip 创建代码:

要将文件下载到临时服务器,您必须首先获得所需的 S3Object 的访问权限。在您的例子中,它是存储在 slack-automation 存储桶中的 slack.xlsx

您提到您想要使用 IAM 角色提供给您的临时凭证。明智之举是不在代码中公开凭据,同时确保提供给服务的凭据将自动刷新。您需要初始化 s3Client 像这样:

AmazonS3Client s3Client = new AmazonS3Client(new InstanceProfileCredentialsProvider());

InstanceProfileCredentialsProvider 从 Amazon EC2 实例元数据服务加载凭证(基于您的 IAM 角色)。

注意:确保所使用的 IAM 角色实际上具有对存储桶的读取访问权限。

要获取S3Object,请使用:

S3Object fileObject = s3Client.getObject(new GetObjectRequest(bucketName, key));

在您的情况下,bucketName 将是 slack-automation, key 将是 S3 存储桶上的文件名称(此处为 slack.xlsx)。

然后,要将文件存储在服务器上,请使用 org.apache.commons.io.FileUtils 中的 copyInputStreamToFile 函数

FileUtils.copyInputStreamToFile(s3Object.getObjectContent(), new File(fileName));

关于java - 如何使用 java 和 AWS 临时凭证从 s3 存储桶下载文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50364136/

相关文章:

java - 使用 Java ProcessBuilder 运行 native Windows .exe 产生错误::目录名称无效

JavaFX:ComboBox<Test>根据Test的ID字段获取和设置项目

java - 有没有类似 LINQ for Java 的东西?

amazon-web-services - 如何在 aws ssm get-parameters-by-path 中正确指定路径?

java - 是否可以将 BufferedWriter 的内容作为字符串获取?

Java保留名编译

amazon-s3 - 如何将 AWS S3 url 转换为 boto 的存储桶名称?

node.js - 从外部 url 下载 pdf 文件 - Heroku、NodeJS、Angular 7

amazon-s3 - S3 : make a public folder private again?

java - AmazonS3.getObject(request).getObjectContent() 频繁出现 NoHttpResponseException