【问题标题】:AWS signed URL too long to shortenAWS 签名 URL 太长,无法缩短
【发布时间】:2018-04-02 13:33:50
【问题描述】:

我正在使用 AWS 创建一个签名 URL,因此我可以安全地将这个 URL 传递给另一个 API 以供临时使用。签名的 URL 指向 S3 资源。问题是其他 API 不接受这么长的链接。因此,我试图缩短它。我尝试使用像 goo.glbit.ly 这样的缩短器无济于事,因为 URL 对他们来说太长了。我什至用 AWS (AWS url shortener) 构建了我自己的私有缩短器,但它有同样的问题:“网站重定向位置的长度不能超过 2,048 个字符。”。

我在 iOS (Swift) 中使用 AWSS3PreSignedURLBuilder.default().getPreSignedURL(preSignedURLRequest) 创建签名 URL,同时将 AWS Cognito 用作未经授权的用户。

我尝试了以下方法无济于事:

  • 选择最短的 S3 存储桶名称(包含 3 个字符)
  • 尽可能缩短文件名。我将文件名限制为 10 个字符加上文件扩展名(总共 14 个字符)。较短的文件名对我来说不可行,因为它们在一定程度上应该是唯一的。

但即使进行了所有这些细微的调整,AWS 返回的签名 URL 有时也太长了。特别是令牌参数(X-Amz-Security-Token)似乎真的很长。通过我的小调整,我有时会得到少于 2,048 个字符的 URL,但有时会稍长一些。我想找到一个解决方案,保证 URL 不会太长并且可以缩短。

在我自己的私有 AWS URL 缩短器中,以下代码 sn-p 创建 S3 对象,该对象重定向到实际的长 URL。

s3.putObject({
    Bucket: s3_bucket,
    Key: key_short,
    Body: "",
    WebsiteRedirectLocation: url_long,
    ContentType: "text/plain"
  },
  (err, data) => {
    if (err) {
      console.log(err);
      done("", err.message);
    } else {
      const ret_url = "https://" + cdn_prefix + "/" + id_short;
      console.log("Success, short_url = " + ret_url);
      done(ret_url, "");
    }
  });

该方法返回以下错误

网站重定向位置的长度不能超过 2,048 字符。

对象元数据中标头“x-amz-website​-redirect-location”的 putObject 文档声明如下 (see: put object documentation):

值的长度限制为 2 KB

如何确保初始 AWS 签名 URL 对于 URL 缩短器来说不会太长?

编辑:

我发现的一个问题是,我在 AWS Cognito 中将签名 URL 创建为未经身份验证的用户。因此,签名的 URL 包含这个长得离谱的令牌作为参数。我不想在 iOS 应用程序中嵌入我的 accessKey 和 shortKey,这就是我切换到 AWS Cognito 的原因(请参阅 aws cognito)。但目前没有授权用户,只有未经授权的用户,我需要将签名 URL 创建为未经授权的 AWS Cognito 用户。如果我使用 accessKey 和 shortKey 使用常规凭据创建签名 URL,我会得到一个更短的 URL。但为此我不得不将我的 accessKey 和 shortKey 嵌入到 iOS 应用程序中,这是不推荐的。

【问题讨论】:

  • 你是如何创建签名网址的?
  • @helloV 我在以未经授权的用户身份使用 AWS Cognito 时使用 AWSS3PreSignedURLBuilder.default().getPreSignedURL(preSignedURLRequest) 创建签名 URL。
  • @helloV 也请查看我对问题的编辑
  • 如果您依赖临时凭据,则无能为力。 “另一种临时使用的 API” 我认为不是您控制的 API。那正确吗?该 API 是否会正确地遵循从缩短器到现有长 URL 的重定向?我有另一种在 AWS 组件上构建私有缩短器的方法,我认为最多可以容纳约 8,192 字节,但必须进一步测试才能看到。签名 URL 内容的性质是什么,您在签名 URL 中使用什么样的过期时间?
  • @Michael-sqlbot 假设我无法控制将缩短的 URL 发送到的其他 API,您是正确的。它只接受很短的 URL。它将正确地遵循从缩短器到现有较长 URL 的重定向。我目前为签名 URL 使用 3 天的到期日期,但将来会缩短它,例如1小时的球场。签名的 URL 应该让调用者有机会检索文件。权限也受到限制,只有特定 IP 才能使用这些签名的 URL。

标签: amazon-web-services url amazon-s3 url-redirection url-shortener


【解决方案1】:

有一种生成预签名 URL 的旧方法会生成非常短的链接,例如:

https://s3-ap-southeast-2.amazonaws.com/my-bucket/foo.png?AWSAccessKeyId=AKI123V12345RYTP123&Expires=1508620600&Signature=oB1/jca2JFXw5DbN7gBKEXkUQk8%3D

但是,这早于 sigv4,因此它在较新的地区不起作用(从法兰克福开始)。

您可以在以下位置找到示例代码:

【讨论】:

  • 不幸的是,我在 EUCentral1。我可以创建一个 lambda,它使用一个允许 s3 getobject 的角色,并在 lambda 函数中使用该角色的访问和密钥创建签名的 url,并使用 AWS cognito 作为未经授权的用户从我的 iOS 应用程序调用该 lambda 函数吗?我将从 iOS 应用程序中调用的 lambda 示例代码将是例如stackoverflow.com/questions/38831829/…
  • 问题是 OP 不想在应用程序中嵌入 IAM 凭证,因此您仍然需要容纳 X-Amz-Security-Token 的额外长度,最长可达 4K 字节。不过,这会比 V4 URL 短。
  • @KaraBenNemsi 这将导致类似的问题 - 使用角色的 Lambda 函数仍会生成具有 X-Amz-Security-Token 的签名 URL。
  • 我刚刚测试了在应用程序中嵌入访问密钥和安全密钥并生成预签名 URL,它给了我一个更短的 URL,而没有 X-Amz-Security-Token。只有X-Amz-AlgorithmX-Amz-CredentialX-Amz-DateX-Amz-ExpiresX-Amz-SignedHeadersX-Amz-Signature。没有包含任何令牌
  • @Michael-sqlbot 我能不能使用具有特定角色的方法(这似乎给了我一个更短的预签名 URL)以及 lambda 中嵌入的访问密钥和安全密钥,并在 lambda 中创建预签名 URL功能。并从 iOS 端调用那个 lambda 函数?
【解决方案2】:

我通过创建用于创建预签名 URL 并返回预签名 URL 的 AWS lambda 解决了这个问题。预签名 URL 允许调用者访问 (getObject) S3 资源。对此有两种选择:

  1. 分配给 AWS lambda 的角色具有 getObject 的 S3 权限。生成的预签名 URL 将包含比使用 AWS Cognito 在 iOS 应用程序中发布的临时凭证创建的预签名 URL 短得多的令牌。
  2. 将具有 getObject 的 S3 权限的角色的访问密钥和秘密密钥直接嵌入到 AWS lambda 中,这将为您提供更短的 URL,因为生成的预签名 URL 中不包含任何令牌。 (例如sample AWS code

我在我的 iOS 应用程序中将此 lambda 称为未经授权的认知用户。从 AWS lambda 接收到预签名 URL 后,我可以缩短它,因为使用这种方法,预签名 URL 会短得多。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-03
    • 1970-01-01
    • 2023-03-28
    • 2020-01-08
    相关资源
    最近更新 更多