【问题标题】:AWS S3 Presigned URL with other query parameters带有其他查询参数的 AWS S3 预签名 URL
【发布时间】:2017-12-06 01:53:56
【问题描述】:

我创建了一个预签名的 URL 并返回类似

的内容
https://s3.amazonaws.com/MyBucket/MyItem/
?X-Amz-Security-Token=TOKEN
&X-Amz-Algorithm=AWS4-HMAC-SHA256
&X-Amz-Date=20171206T014837Z
&X-Amz-SignedHeaders=host
&X-Amz-Expires=3600
&X-Amz-Credential=CREDENTIAL
&X-Amz-Signature=SIGNATURE

我现在可以curl 这没问题。但是,如果我现在添加另一个查询参数,我将返回 403,即

https://s3.amazonaws.com/MyBucket/MyItem/
?X-Amz-Security-Token=TOKEN
&X-Amz-Algorithm=AWS4-HMAC-SHA256
&X-Amz-Date=20171206T014837Z
&X-Amz-SignedHeaders=host
&X-Amz-Expires=3600
&X-Amz-Credential=CREDENTIAL
&X-Amz-Signature=SIGNATURE
&Foo=123

怎么会?是否可以生成支持自定义查询的预签名url?

【问题讨论】:

    标签: amazon-web-services amazon-s3


    【解决方案1】:

    将自定义查询参数插入到 v4 预签名 URL 中似乎在技术上是可行的,它被签名之前,但并非所有 AWS 开发工具包都公开了执行此操作的方法。 p>

    以下是使用 AWS JavaScript SDK 执行此操作的迂回方式示例:

    const AWS = require('aws-sdk');
    
    var s3 = new AWS.S3({region: 'us-east-1', signatureVersion: 'v4'});
    var req = s3.getObject({Bucket: 'mybucket', Key: 'mykey'});
    req.on('build', () => { req.httpRequest.path += '?session=ABC123'; });
    console.log(req.presign());
    

    我已经尝试过使用以 X- 开头的自定义查询参数,而没有它。两者似乎都工作正常。我已经尝试了多个查询参数 (?a=1&b=2),而且效果也很好。

    自定义的预签名 URL 可以正常工作(我可以使用它们来获取 S3 对象),并且查询参数会将其放入 CloudWatch Logs,因此可以用于关联目的。

    请注意,如果您想提供自定义过期时间,请按以下方式进行操作:

    const Expires = 120;
    const url = req.presign(Expires);
    

    我不知道其他(非 JavaScript)SDK 允许您像这样将查询参数插入到 URL 构造过程中,因此在其他语言中执行此操作可能是一个挑战。我建议使用小型 JavaScript Lambda 函数(或 API Gateway 加 Lambda 函数),它可以简单地创建并返回自定义的预签名 URL。

    自定义查询参数也是防篡改的。它们包含在 URL 的签名中,因此,如果您篡改它们,URL 将变为无效,产生 403 Forbidden。

    我使用此代码生成了您的预签名 URL。结果是:

    https://s3.amazonaws.com/MyBucket/MyItem
    ?Foo=123
    &X-Amz-Algorithm=AWS4-HMAC-SHA256
    &X-Amz-Credential=AKIA...27%2Fus-east-1%2Fs3%2Faws4_request
    &X-Amz-Date=20180427T0012345Z
    &X-Amz-Expires=3600
    &X-Amz-Signature=e3...7b
    &X-Amz-SignedHeaders=host
    

    这些都不能保证这项技术将继续有效,当然,如果 AWS 在幕后改变了一些东西,但目前它似乎有效并且肯定有用。

    归因:此发现的来源是aws-sdk-js/issues/502

    【讨论】:

    • 谢谢@jarmod,它已经快 3 年了,这仍然有效.....
    【解决方案2】:

    如果您更改其中一个标题或添加/减去,那么您必须退出 URL。

    这是 AWS 签名设计的一部分,此过程旨在实现更高级别的安全性。 AWS 从签名版本 2 更改为签名版本 4 的原因之一。

    签名设计不知道哪些标头重要,哪些不重要。这将造成试图跟踪所有 AWS 服务的噩梦。

    【讨论】:

      【解决方案3】:

      我为 Ruby SDK 创建了这个解决方案。这有点像 hack,但它可以按预期工作:

      require 'aws-sdk-s3'
      require 'active_support/core_ext/object/to_query.rb'
      
      # Modified S3 pre signer class that can inject query params to the URL
      #
      # Usage example:
      #
      #    bucket_name = "bucket_name"
      #    key = "path/to/file.json"
      #    filename = "download_file_name.json"
      #    duration = 3600
      #
      #    params = {
      #      bucket: bucket_name,
      #      key: key,
      #      response_content_disposition: "attachment; filename=#{filename}",
      #      expires_in: duration
      #    }
      #
      #    signer = S3PreSignerWithQueryParams.new({'x-your-custom-field': "banana", 'x-some-other-field': 1234})
      #    url = signer.presigned_url(:get_object, params)
      #
      #    puts "url = #{url}"
      #
      class S3PreSignerWithQueryParams < Aws::S3::Presigner
        def initialize(query_params = {}, options = {})
          @query_params = query_params
          super(options)
        end
      
        def build_signer(cfg)
          signer = super(cfg)
          my_params = @query_params.to_h.to_query()
          signer.define_singleton_method(:presign_url,
                                         lambda do |options|
                                           options[:url].query += "&" + my_params
                                           super(options)
                                         end)
          signer
        end
      end
      

      【讨论】:

      • 感谢@DavidRissatoCruz。我想试一试,但没有看到我的代码命中了 build_signer 方法 - 查看源文档并尝试追踪它,我想知道是否还有其他我应该包括的内容?
      【解决方案4】:

      虽然没有记录,但您可以将参数作为参数添加到对 presigned_url 的调用中。

      obj.presigned_url(:get, 
        expires_in: expires_in_sec, 
        response_content_disposition: "attachment"
      )
      
      https://bucket.s3.us-east-2.amazonaws.com/file.txt?response-content-disposition=attachment&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=PUBLICKEY%2F20220309%2Fus-east-2%2Fs3%2Faws4_request&X-Amz-Date=20220309T031958Z&X-Amz-Expires=43200&X-Amz-SignedHeaders=host&X-Amz-Signature=SIGNATUREVALUE
      

      【讨论】:

      • 你知道我们可以使用的参数的文档在哪里吗?
      猜你喜欢
      • 2018-10-20
      • 2019-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-27
      • 1970-01-01
      相关资源
      最近更新 更多