AWS 签名的 v4 PUT 请求预签名 URL 上的SignatureDoesNotMatch

问题描述 投票:0回答:2

目前,我在为 PUT 请求创建有效的签名 v4 预签名 url 时遇到问题。

URL 在服务器端生成,然后提供给客户端。 客户端应使用 URL 通过 API 网关将文件上传到 Amazon S3 存储桶中。 为了验证请求 API Gateway IAM 身份验证。

对于我的用例,无法通过“s3-presigned-url”直接上传到 S3 存储桶。

以下代码描述了预签名 url 的生成,并用 Typescript 编写。签名v4 url的生成是基于AWS提供的包@aws-sdk/signature-v4。

import { SignatureV4 } from "@aws-sdk/signature-v4";
import { Sha256 } from "@aws-crypto/sha256-js";
import { formatUrl } from "@aws-sdk/util-format-url";

const createSignedUrl = async (credentials: {
  accessKeyId: string,
  secretAccessKey: string,
  sessionToken: string,
}, requestParams: {
  method: "GET" | "PUT",
  host: string,
  protocol: string,
  path: string,
}) => {
  const sigv4 = new SignatureV4({
    service: "execute-api",
    region: process.env.AWS_REGION!,
    credentials: {
      accessKeyId: credentials.accessKeyId,
      secretAccessKey: credentials.secretAccessKey,
      sessionToken: credentials.sessionToken,
    },
    sha256: Sha256,
    applyChecksum: false
  });

  const signedUrlRequest = await sigv4.presign({
    method: requestParams.method,
    hostname: requestParams.host,
    path: requestParams.path,
    protocol: requestParams.protocol,
    headers: {
      host: requestParams.host,
    },
  }, {
    expiresIn: EXPIRES_IN,
  });

  const signedUrl = formatUrl(signedUrlRequest);
  return signedUrl
};

我使用 Postman 来测试预先输入的网址。

如果我为 GET 请求生成预签名 URL,则一切正常。

如果我为 PUT 请求生成预签名 url,并且不在 Postman 中为 PUT 请求设置正文,则一切正常。但我的存储桶中有一个空文件;-(.

如果我为 PUT 请求生成预签名 url 并在 Postman 中设置正文(通过正文 -> 二进制 -> [选择文件]),它会失败!

错误信息:

我们计算的请求签名与您提供的签名不匹配。 ...

AWS 文档 https://docs.aws.amazon.com/general/latest/gr/create-signed-request.html 描述了负载必须在规范请求中进行哈希处理。但当时我没有有效负载。

如果我想为发送到 API 网关的 PUT 请求生成预签名 URL(如 AWS S3 服务文档中所述),是否还有 UNSIGNED-PAYLOAD 选项? 如何配置 SignatureV4 对象或 presign(...) 方法调用以使用 UNSIGNED-PAYLOAD 生成有效的 PUT 请求 URL?

amazon-web-services amazon-iam aws-api-gateway
2个回答
1
投票

我能够将生成的规范请求与 Amazon API Gateway 预期的规范请求进行比较。 无论我是否将查询参数 X-Amz-Content-Sha256=UNSIGNED-PAYLOAD 添加到 URL,Amazon API Gateway always 都需要有效负载的哈希值。 因此,选项“UNSIGNED-PAYLOAD”作为 API Gateway IAM 身份验证的规范请求哈希值是不可能的,而 Amazon S3 服务则可以。


0
投票

您可以将未签名的有效负载与单个块一起使用,以下是方法(我构建了自己的基于 Coldfusion 的 AWS4 签名器,因此您必须弄清楚将其放在哪里)

在签名者中,我设置: X-Amz-Content-Sha256:未签名的有效负载 (不要散列!) 对于散列有效负载:“UNSIGNED-PAYLOAD”(不要散列!)

在标题中: X-Amz-Content-Sha256 = 未签名有效负载 然后身体就可以得到它需要发送的任何东西。

© www.soinside.com 2019 - 2024. All rights reserved.