使用预先签名的 URL 将文件放入 S3

2024-03-25

我整夜都在使用 Amazon S3 预签名 URL 来尝试 PUT 文件。我在 java 代码中生成预签名 URL。

    AWSCredentials credentials = new BasicAWSCredentials( accessKey, secretKey );
    client = new AmazonS3Client( credentials );
    GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest( bucketName, "myfilename", HttpMethod.PUT);
    request.setExpiration( new Date( System.currentTimeMillis() + (120 * 60 * 1000) ));
    return client.generatePresignedUrl( request ).toString();

然后,我想使用生成的预签名 URL 来使用curl 放置文件。

curl -v -H "content-type:image/jpg" -T mypicture.jpg https://mybucket.s3.amazonaws.com/myfilename?Expires=1334126943&AWSAccessKeyId=<accessKey>&Signature=<generatedSignature>

我认为,就像 GET 一样,这可以在非公开的存储桶上工作(这就是预签名的意义,对吧?)好吧,我每次尝试都被拒绝访问。最后出于沮丧,我更改了存储桶的权限以允许每个人都可以写入。当然,这样预签名的 URL 就起作用了。我很快从存储桶中删除了 EVERYONE 权限。现在,我无权删除通过我自己的自预签名 URL 上传到我的存储桶中的项目。我see now http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTObjectPUT.html我可能应该在我上传的内容上添加 x-amz-acl 标头。我怀疑在我做对之前我会创建更多不可删除的对象。

这引出了几个问题:

  • 如何使用 PUT 和生成的预签名 URL 通过curl 进行上传?
  • 如何删除上传的文件和我创建的用于测试它的存储桶?

最终目标是手机将使用此预签名 URL 来 PUT 图像。我正在尝试将其作为概念证明进行卷曲。

Update:我问了一个问题亚马逊论坛 https://forums.aws.amazon.com/thread.jspa?threadID=91800。如果那里提供了答案,我会将其作为答案放在这里。


这确实有点令人费解,我认为这是一个错误适用于 Java 的 AWS 开发工具包 http://aws.amazon.com/sdkforjava/(见下文) - 但首先也是最重要的,以下curl http://curl.haxx.se/命令将这样上传您的文件(当然假设更新了预签名 URL):

curl -v -T mypicture.jpg https://mybucket.s3.amazonaws.com/myfilename?Expires=1334126943&AWSAccessKeyId=<accessKey>&Signature=<generatedSignature>

也就是说,我已经排除了Content type标头,产生application/octet-stream (or binary/octet-stream) 结果,这显然是不希望的;因此,需要进一步挖掘。

背景/分析

PUT(以及 DELETE 和 HEAD)请求的预签名 URL亚马逊S3 http://aws.amazon.com/s3/众所周知,原则上是有效的,而不是在本网站上的相关问题中最不明显的证据(例如,参见我的回答)使用预签名 URL 通过curl 上传到 s3(获取 403) https://stackoverflow.com/a/9085141/45773).

便利的查询字符串请求身份验证替代方案 http://docs.amazonwebservices.com/AmazonS3/latest/dev/RESTAuthentication.html#RESTAuthenticationQueryStringAuth已记录使用以下内容说明查询字符串请求身份验证方法的伪语法:

StringToSign = HTTP-VERB + "\n" +
    Content-MD5 + "\n" +
    Content-Type + "\n" +
    Expires + "\n" +
    CanonicalizedAmzHeaders +
    CanonicalizedResource;    

它确实包括Content-Type标头,并且(正如您已经发现的那样)这是某些记录案例中缺失的部分,请参见例如AWS 团队的回应带有 PUT 请求的 GetPreSignedURL https://forums.aws.amazon.com/message.jspa?messageID=244858#244858,添加后会生成一个有效的预签名 URL。

这很容易实现适用于 .NET 的 AWS 开发工具包 http://aws.amazon.com/sdkfornet/确实,这提供了方便的方法GetPreSignedUrlRequest.WithContentType http://docs.amazonwebservices.com/sdkfornet/latest/apidocs/html/M_Amazon_S3_Model_GetPreSignedUrlRequest_WithContentType.htm为此:

设置此请求的 ContentType 属性。该属性默认 到“二进制/八位字节流”,但如果您需要其他东西,您可以 设置该属性。

因此,扩展相应的样本使用预签名 URL 上传对象 - 适用于 .NET 的 AWS 开发工具包 http://docs.amazonwebservices.com/AmazonS3/latest/dev/UploadObjectPreSignedURLDotNetSDK.html如下生成一个具有内容类型的工作预签名 URL,可以通过以下方式上传curl正如预期的那样(即完全按照您的尝试):

    // ...
    GetPreSignedUrlRequest request = new GetPreSignedUrlRequest();
    // ...
    request.WithContentType("image/jpg");
    // ...

现在,我们想扩展语义相同的样本使用预签名 URL 上传对象 - AWS SDK for Java http://docs.amazonwebservices.com/AmazonS3/latest/dev/PresignedUrlUploadObjectDotNetSDK.html以类似的方式,但是(正如您也已经发现的那样),没有专门的方法来实现这一点。但这可能只是一种缺乏便利的方法,可以通过以下方式实现添加请求参数() http://docs.amazonwebservices.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/model/GeneratePresignedUrlRequest.html#addRequestParameter%28java.lang.String,%20java.lang.String%29 or 设置响应头() http://docs.amazonwebservices.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/model/GeneratePresignedUrlRequest.html#setResponseHeaders%28com.amazonaws.services.s3.model.ResponseHeaderOverrides%29最终,例如:

  // ...
  request.setExpiration( new Date( System.currentTimeMillis() + (120 * 60 * 1000) ));
  request.addRequestParameter("content-type", "image/jpg");
  return client.generatePresignedUrl( request ).toString();
  // ...

然而,这两种方法的文档都表明了其他目的,并且它确实不起作用,即它们总是产生相同的签名,无论像这样设置哪种内容类型(如果有)。

进一步调试 SDK 发现,两者都提供了语义相似的核心方法来根据伪语法上面提到的,参见构建签名字符串() https://github.com/amazonwebservices/aws-sdk-for-net/blob/master/Amazon.S3/AmazonS3Client.cs#L6173对于 .NET 和makeS3CanonicalString() https://github.com/amazonwebservices/aws-sdk-for-java/blob/master/src/main/java/com/amazonaws/services/s3/internal/RestUtils.java#L57对于Java。

但Java版本中的相应代码为将所有感兴趣的标题添加到列表中,然后对它们进行排序, where “有趣”定义为 Content-MD5、Content-Type、Date 和 x-amz-事实上从未执行过,因为确实没有方法以某种方式提供这些标头,这些标头仅适用于类默认请求 http://docs.amazonwebservices.com/AWSJavaSDK/latest/javadoc/com/amazonaws/DefaultRequest.html而不是阶级生成预签名 URL 请求 http://docs.amazonwebservices.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/model/GeneratePresignedUrlRequest.html用于初始化前者,依次作为计算签名的输入,参见protected方法创建请求() https://github.com/amazonwebservices/aws-sdk-for-java/blob/master/src/main/java/com/amazonaws/services/s3/AmazonS3Client.java#L2593.

有趣/值得注意的是,在 .NET 与 Java 中计算查询字符串身份验证的两种方法的输入几乎是相反的组合:header vs. 范围调用堆栈上的源代码,这可能暗示 Java bug 的原因,但显然这也可能很难破译,即内部架构当然可能有很大不同。

初步结论

对此有两个角度:

  • AWS SDK for Java 肯定缺乏设置内容类型的便捷方法,这可能是一种相对罕见的方法,但在其他 AWS SDK 中也有明显的用例 - 这是令人惊讶的,因为它在 AWS 相关后端服务中广泛使用。
  • 无论如何,这种方式似乎有些可疑查询字符串请求身份验证例如,与 .NET 版本相比,这再次令人惊讶,因为它是核心功能,但是,它仍然在 S3 模型/命名空间内,因此可能只有上面的各个用例需要。

总之,解决此问题的唯一合理方法是更新 SDK,因此需要提交错误报告 - 显然,人们也可以复制/扩展 SDK 功能以单独解决这种特殊情况(理想情况下以允许提交的方式)的拉取请求aws-sdk-for-java 项目 https://github.com/amazonwebservices/aws-sdk-for-java),但以兼容且可维护的方式做到这一点似乎有点棘手,因此最好由 SDK 维护人员自己完成。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用预先签名的 URL 将文件放入 S3 的相关文章

  • Java 7 默认语言环境

    我刚刚安装了 jre7 我很惊讶地发现我的默认区域设置现在是 en US 对于jre6 它是de CH 与jre7有什么不同 默认区域设置不再是操作系统之一吗 顺便说一句 我使用的是Windows7 谢谢你的回答 编辑 我已经看到了语言环境
  • Oracle Java 教程 - 回答问题时可能出现错误

    我是 Java 新手 正在阅读 Oracle 教程 每个部分之后都有问题和答案 我不明白一个答案中的一句话 见下面的粗体线 来源是https docs oracle com javase tutorial java javaOO QandE
  • Base36 编码字符串?

    我一直在网上查找 但找不到解决此问题的方法 在 Python Ruby 或 Java 中 如何对以下字符串进行 Base 36 编码 nOrG9Eh0uyeilM8Nnu5pTywj3935kW 5 Ruby 以 36 为基数 s unpa
  • 如何将jscrollpane添加到jframe?

    我有以下源代码 有人可以给我建议如何将 jscrollpane 添加到 jframe 上吗 我尝试了几次将其添加到 jframe 但没有任何进展 它甚至没有显示 public class Form3 JFrame jframe new JF
  • 使用第三方库记录来自 PHP 应用程序的所有 cURL 请求

    好吧 我的 PHP Yii2 应用程序遇到了困难 我需要记录来自应用程序的每个传入和传出请求 传入的请求可以轻松地记录在 PHP 本身中 在引导阶段添加一些处理程序 这很容易 但真正的问题是我正在使用许多第三方库 即 Amazon MWS
  • 埃拉托色尼筛法 - 实现返回一些非质数值?

    我用 Java 实现了埃拉托斯特尼筛法 通过伪代码 public static void sieveofEratosthenes int n boolean numArray numArray new boolean n for int i
  • 您建议使用哪种压缩(GZIP 是最流行的)servlet 过滤器?

    我正在寻找一个用于大容量网络应用程序的 GZIP servlet 过滤器 我不想使用容器特定的选项 要求 能够压缩响应负载 XML Faster 已在大批量应用的生产中得到验证 应适当设置适当内容编码 跨容器移植 可选择解压缩请求 谢谢 我
  • 是否可以从 servlet 内部以编程方式设置请求上下文路径?

    这是一个特殊情况 我陷入了处理 企业 网络应用程序的困境 企业应用程序正在调用request getContext 并将其与另一个字符串进行比较 我发现我可以使用 getServletContext getContextPath 获取 se
  • org/codehaus/plexus/archiver/jar/JarArchiver(不支持的major.minor版本49.0)-Maven构建错误

    下午大家 我在尝试构建项目时收到上述错误 我很确定这与使用 Java 1 6 编译的 Maven 最新更新有关 而我们尝试构建的项目是 1 4 项目 在此之前的插件工作没有问题 因此我将以下内容添加到 POM xml 文件中以尝试强制使用现
  • 从直方图计算平均值和百分位数?

    我编写了一个计时器 可以测量任何多线程应用程序中特定代码的性能 在下面的计时器中 它还会在地图中填充花费了 x 毫秒的调用次数 我将使用这张图作为我的直方图的一部分来进行进一步的分析 例如调用花费了这么多毫秒的百分比等等 public st
  • 当 minifyEnabled 为 true 时 Android 应用程序崩溃

    我正在使用多模块应用程序 并且该应用程序崩溃时minifyEnabled true in the installed模块的build gradle 以下是从游戏控制台检索到的反混淆堆栈跟踪 FATAL EXCEPTION Controlle
  • Java:如何确定文件所在的驱动器类型?

    Java 是否有一种独立于平台的方法来检测文件所在的驱动器类型 基本上我有兴趣区分 硬盘 可移动驱动器 如 USB 记忆棒 和网络共享 JNI JNA 解决方案不会有帮助 可以假设 Java 7 您可以使用 Java 执行 cmd fsut
  • 如何从日期中删除毫秒、秒、分钟和小时[重复]

    这个问题在这里已经有答案了 我遇到了一个问题 我想比较两个日期 然而 我只想比较年 月 日 这就是我能想到的 private Date trim Date date Calendar calendar Calendar getInstanc
  • 如何通过 Android 按钮单击运行单独的应用程序

    我尝试在 Android 应用程序中添加两个按钮 以从单独的两个应用程序订单系统和库存系统中选择一个应用程序 如图所示 我已将这两个应用程序实现为两个单独的 Android 项目 当我尝试运行此应用程序时 它会出现直到正确选择窗口 但是当按
  • 在 Clojure 中解压缩 zlib 流

    我有一个二进制文件 其内容由zlib compress在Python上 有没有一种简单的方法可以在Clojure中打开和解压缩它 import zlib import json with open data json zlib wb as
  • 如何停止执行的 Jar 文件

    这感觉像是一个愚蠢的问题 但我似乎无法弄清楚 当我在 Windows 上运行 jar 文件时 它不会出现在任务管理器进程中 我怎样才能终止它 我已经尝试过 TASKKILL 但它对我也不起作用 On Linux ps ef grep jav
  • JAVA中遍历JSON数据

    我是 JSON 新手 我使用 HTTPUrlConnections 并在 JAVA 程序中获得一些响应 响应数据将类似于 data id 1 userId 1 name ABC modified 2014 12 04 created 201
  • 如何从 Ant 启动聚合 jetty-server JAR?

    背景 免责声明 I have veryJava 经验很少 我们之前在 Ant 构建期间使用了 Jetty 6 的包装版本来处理按需静态内容 JS CSS 图像 HTML 因此我们可以使用 PhantomJS 针对 HTTP 托管环境运行单元
  • JMS 中的 MessageListener 和 Consumer 有什么区别?

    我是新来的JMS 据我了解Consumers能够从队列 主题中挑选消息 那么为什么你需要一个MessageListener因为Consumers会知道他们什么时候收到消息吗 这样的实际用途是什么MessageListener 编辑 来自Me
  • 使用 Java https 上传到 Imgur v3 错误

    我目前正在尝试使用他们当前的 API v3 上传到 imgur 但是我不断收到错误 错误 javax net ssl SSLException 证书中的主机名不匹配 api imgur com imgur com OR imgur com

随机推荐

  • 滚动您自己的明文 Wiki(数据库内的 Wiki)

    有人知道用于创建类似 wiki 的数据存储的 API 最好是 PHP 但我对任何语言都感兴趣 关于滚动您自己的纯文本 wiki 的任何资源怎么样 其他纯文本 wiki 如何处理文本文件的格式 我知道我可以使用 Markdown 或 Text
  • 现有模型和数据库表的rails g脚手架

    我想创建一个结构rails g scaffold Article 但我已经创建了表Articles和型号Articles 有什么办法可以做到这一点吗 rails generate scaffold controller Article
  • 如何在Plotly(python)中设置背景颜色,标题?

    下面是我的代码 有人可以告诉我如何设置背景颜色 标题 x轴y轴标签 scatterplot plot Scatter x x index y x rating mode markers marker dict size 10 color x
  • PHP 中的 Switch-Case 和 If-Else 有什么区别?

    我正在决定是否使用if else vs switch case在我正在编写的一个 PHP 网站中 我想知道使用其中之一是否有任何好处 或者是否在某些情况下打算使用其中一种而不是另一种 有趣的问题 因为在编译语言 甚至是 JIT 语言 中 使
  • 使 'week' 函数为双周

    嗨 这一切应该是一个简单的问题 我只是似乎无法弄清楚 我想每两周分解一次该数据集 以便以两周为间隔查看年度周期 我不想总结或汇总数据 我想做的正是 周 函数正在做的事情 但每两周一次 下面是数据和代码的示例 任何帮助将不胜感激 DF lt
  • 棋盘坐标

    我正在尝试用 Java 创建一个国际象棋程序 现在 我已经将棋盘与现有的部件一起完成 我可以用鼠标通过拖放来移动它们 我需要的是向两侧的方块添加坐标 就像在真正的板上一样 不一定要有什么奇特的东西 只是一个视觉效果 由于我没有使用图形绘制板
  • 使用触发器将数据从 SQL Server 插入到 MySql

    我有两个数据库 一个在 SQL Server 中 另一个在 MySql 中 我想在 SQL Server 表中进行插入时将数据插入 MySQL 表中 是否可以在 SQL Server 中使用触发器 请给我一个答案 您可以从以下位置创建连接M
  • 可以触发流选择特定文件

    我的程序连续读取流hadoop文件夹 比如 hadoopPath 它从上面的文件夹中选取所有文件 我可以只显示该文件夹的特定文件类型吗 例如 hadoopPath log 我还有一个与 Spark 和流媒体相关的问题 Spark Strea
  • 在 Kinect 示例中用 Google Earth 地球仪替换可平移的世界地图图像

    我需要有关如何使用 Kinect 手势而不是使用鼠标 键盘导航来控制 Google 地球的基本指导 我已经运行了 Kinect Developer 工具包示例 并且有一个名为 C 的交互式画廊 允许平移世界地图 它是静态图像 这是其文档的链
  • Firebase函数-查询firestore

    我试图从云函数中的 firestore 检索一些数据 但什么也没有得到 客户端上的相同查询给出了正确的结果 这可能是小事 但我没有看到问题 我究竟做错了什么 const functions require firebase function
  • 使用范围,如何将 .COPY DESTINATION 粘贴为值

    我有以下代码 可以很好地将整个单元格复制到新的目的地 Dim ws As Worksheet rng As Range Set ws Sheets Duplicates Set rng ws Range A2 rng Copy Destin
  • 在 Get-ADUser 筛选器参数中传递字符串会导致错误 - 在 pscustomobject 中找不到属性

    我正在尝试创建一个新的 Active Directory 用户 但首先我验证该用户不存在Get ADUser 我从人力资源部门导入用户数据并构建自定义属性 newUsers Import Csv csvFile Select Object
  • 如何查看 int 数组中的元素是否为空?

    example 我想看看是否array 5 保存一个值或者为空 原始数组中的元素不能为空 它们总是会被初始化为某些东西 通常是0 for int数组 但取决于您如何声明数组 如果您像这样声明数组 例如 int myArray myArray
  • 以编程方式执行 spring roo

    我查看了 spring roo 我发现我们可以使用命令提示符生成实体 控制器和其他实体 但我需要从文本框中获取实体名称和字段名称作为用户输入 然后使用 roo 生成项目 我正在使用Windows 您可以创建脚本文件 然后使用 roo 执行该
  • Internet Explorer 和 jQuery 的“权限被拒绝”

    我尝试使用 jQuery 进行 AJAX 调用 post在 Internet Explorer 中 但我得到的只是一条错误消息 权限被拒绝 这个问题有点奇怪 因为只有当我在访问任何其他页面之后访问一个页面时才会出现这种情况 例如 我在地址行
  • 无法使用 firebase 函数获取 req.path 和 req.query.abc

    我正在尝试获取请求查询参数和网址firebase functions 这是我正在使用的代码 firebase json hosting public build rewrites source getCoins function getCo
  • Java - 如何测试 Catch 块?

    有点转发 但是关于没有足够声誉的第 22 条军规意味着我无法对任何重复的线程发表评论 咳嗽 我正在尝试使用 Mockito 测试 try catch 的 catch 块 是否可以使模拟抛出由正在测试的方法处理的异常 我无法使用 doThro
  • 为什么 return 不遵守finally 块中变量的值?

    finally总是最后执行 所以语句x 3应该最后执行 但是 运行此代码时 返回的值为 2 Why class Test public static void main String args System out println fina
  • 使用 AVPlayer 进行串流速度很慢

    我使用 AVPlayer 从互联网上传输 mp3 文件 但它的运行速度非常慢 使用探查器 我发现它首先下载整个文件 然后开始播放 有什么解决方法吗 现在 我正在使用这段代码 if let player player Notification
  • 使用预先签名的 URL 将文件放入 S3

    我整夜都在使用 Amazon S3 预签名 URL 来尝试 PUT 文件 我在 java 代码中生成预签名 URL AWSCredentials credentials new BasicAWSCredentials accessKey s