SignatureDoesNotMatch在AWS签名的v4 PUT请求预签名url



目前,我有一个问题,即为PUT请求创建一个有效的签名v4预签名url。

url在服务器端生成,然后提供给客户机。客户端应该使用url通过API网关将文件上传到Amazon S3桶中。使用API网关IAM鉴权对请求进行鉴权

对于我的用例,通过" S3 - pressed -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来测试输出的url。

如果我为GET请求生成一个预先指定的url,一切都可以正常工作。

如果我为一个PUT请求生成一个预先指定的url,并且不为这个PUT请求在Postman中设置body,那么一切都可以正常工作。但是我的桶里有一个空文件;-

如果我为一个PUT请求生成一个预先指定的url并在Postman中设置一个body(通过body ->二进制→[select file]),它失败了!

错误信息:

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

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

如果我想为发送到API网关的PUT请求生成预先指定的url,是否还有UNSIGNED-PAYLOAD选项,就像AWS S3服务文档中描述的那样?我如何配置SignatureV4对象或preign(…)方法调用生成一个有效的PUT请求url与UNSIGNED-PAYLOAD?

我能够将生成的规范化请求与Amazon API Gateway所期望的规范化请求进行比较。Amazon API网关总是无论我是否将查询参数X-Amz-Content-Sha256=UNSIGNED-PAYLOAD添加到url,都期望有效载荷的哈希值。因此选项"UNSIGNED-PAYLOAD"作为API网关IAM认证的规范请求哈希值是不可能的,因为Amazon S3服务是可能的。

最新更新