通过 Java 下载 AWS S3 文件。身份验证调用失败
Posted
技术标签:
【中文标题】通过 Java 下载 AWS S3 文件。身份验证调用失败【英文标题】:AWS S3 file download via Java. Failing on Authentication call 【发布时间】:2022-01-18 20:53:39 【问题描述】:我正在尝试通过 Java 从 AWS S3 存储桶下载 JSON 文件。
该文件由名为 Zuora 的第 3 方计费应用程序创建。
第一步是使用 OAuth 凭据生成文件。然后我得到一个带有文件 URL 的响应。我可以通过浏览器访问它并将其下载到我的桌面,但是当我尝试通过 Java 处理文件时,我遇到了问题。
我在网上看到的每一个地方都发现人们似乎已经通过使用 AWS 库中的 AmazonS3Client 克服了类似的问题。参考:AWS S3 Java SDK - Download file help
我已经尝试过了,但是当我通过第 3 方访问存储桶时,我没有 Auth ID 和 Secret 来创建凭据来拨打电话。
我是否需要这些凭证才能对 AWS S3 上的存储桶进行 GET 调用?我想我不应该,因为我没有尝试创建文件或存储桶等。我无法在没有凭据的情况下通过 java 下载文件。
下面我添加了我试图从中下载文件的 URL 和 Java 代码。
带有 URL 的 Zuora 响应: “数据”: “id”:“fec47238-6a0f-48ef-9fb2-c7e24da886d5”, "query": "select i.AccountId, i.Amount, i.PostedDate, i.InvoiceNumber, i.Status, i.Id from Invoice i, Subscription s where i.Status = 'Posted' and i.Amount > 0 and i.AccountId = s.AccountId 和 s.Id = '8ad084a67d58433a017d5cd0682c0b89'", “useIndexJoin”:假, "sourceData": "直播", "queryStatus": "完成", "dataFile": "**https://bucket-name.s3.us-west-2.amazonaws.com/file-name.jsonl?X-Amz-Security-Token=some-tokenX-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20211215T110928Z&X-Amz-SignedHeaders=host&X-Amz-Expires=14400&X-Amz-Credential=Some-Credential&X-Amz-Signature=some-Signature**", “输出行”:1, “处理时间”:1918, “剩余重试次数”:3, “重试”:3, "updatedOn": "2021-12-15T11:09:28.123Z", “createdBy”:“一些 ID”
2 Java:
private final AmazonS3 amazonS3Client = AmazonS3ClientBuilder.standard().withRegion(Regions.US_WEST_2).build();
try (final S3Object s3Object = amazonS3Client.getObject("bucket-name.s3.us-west-2.amazonaws.com",
"file-name.jsonl");
final InputStreamReader streamReader = new InputStreamReader(s3Object.getObjectContent(), StandardCharsets.UTF_8);
final BufferedReader reader = new BufferedReader(streamReader))
System.out.println(reader.lines().collect(Collectors.toSet()));
错误:com.amazonaws.services.s3.model.AmazonS3Exception:访问被拒绝(服务:Amazon S3;状态代码:403;错误代码:AccessDenied;
【问题讨论】:
Zuora 返回一个签名的 ulr,这是一个公共的 url,但是有一个特定的过期时间。您不需要 s3 客户端。您需要在 Java 中实现 OAuth 流程并只需下载 URL。在外部创建 URL 并复制到您的代码中将不起作用。 这很有趣。因此,如果我执行初始查询以通过 Java 生成来自 Zuora 的响应,那么我可以在上面的问题中使用 Java 下载文件而无需显式传递凭据? 您上面的 Java 代码使用的是 Amazon S3 Java V1 API,并且始终需要凭据。请参阅下面的答案。 @randomG765 对于签名的 url,您不需要 s3 客户端。使用任何 http 客户端库下载它。但是,您无法存储 url。您需要每次都创建它。 @smac2020 您的回答对我有用,谢谢。我不再使用 S3 客户端,而是按照您在下面的回答中所述解析 URL。 【参考方案1】:要使用由 AWS 开发工具包公开的服务客户端,您需要凭据。这在开发人员指南 - 适用于 Java 2.x 的 AWS 开发工具包中指定:
https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
话虽如此 - 如果 S3 存储桶中的对象已使用 S3Presigner object 预签名并且存在预签名 URL,则您可以使用 Java URI 对象访问该对象,而无需使用凭据(假设您在规定时间内这样做)期间)。
要了解有关预签名的更多信息 - 请参阅 DEV 指南中的此主题:
Working with Amazon S3 presigned URLs
这是一个小的 Java SWING 应用程序,它可以使用预签名 URL 从 Amazon S3 存储桶获取内容。
这里不需要信用。
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
class Swing implements ActionListener
JFrame frame=new JFrame();
JButton button=new JButton("Click Me");
Swing()
prepareGUI();
buttonProperties();
public void prepareGUI()
frame.setTitle("My Window");
frame.getContentPane().setLayout(null);
frame.setVisible(true);
frame.setBounds(200,200,400,400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
public void buttonProperties()
button.setBounds(130,200,100,40);
frame.add(button);
button.addActionListener(this);
@Override
public void actionPerformed(ActionEvent e)
//Get a presigned PDF from an Amazon S3 bucket.
try
URL url = new URL("<Specify PRESIGNED URL> ") ;
InputStream in = null;
in = url.openStream();
FileOutputStream fos = new FileOutputStream(new File("C:\\AWS\\yourFile2.txt"));
System.out.println("reading from resource and writing to file...");
int length = -1;
byte[] buffer = new byte[1024];// buffer for portion of data from connection
while ((length = in.read(buffer)) > -1)
fos.write(buffer, 0, length);
fos.close();
in.close();
System.out.println("File downloaded");
catch (IOException ex)
ex.printStackTrace();
public class HelloWorldSwing
public static void main(String[] args)
new Swing();
【讨论】:
以上是关于通过 Java 下载 AWS S3 文件。身份验证调用失败的主要内容,如果未能解决你的问题,请参考以下文章
AWS Java SDK - AWS 身份验证需要有效的 Date 或 x-amz-date 标头
(iOS) AWS S3 上传失败且没有错误(使用联合身份验证的用户 - Apple SSO)
通过 jclouds 使用 AWS (S3) - 如何承担角色