You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

生成带自定义元数据的S3 PUT预签名URL时签名不匹配问题

S3带自定义元数据的PUT预签名URL签名不匹配问题解决思路

问题场景

生成携带自定义元数据mk1:mv1的S3 PUT预签名URL后,使用curl请求时收到签名不匹配错误:

The request signature we calculated does not match the signature you provided. Check your key and signing method.

生成URL的Java代码

public URL generatePushResourceLocation(DocumentId documentId, String contentMD5) {
    String key = documentId.getId().toString();
    PutObjectRequest.Builder putObjectRequestBuilder = PutObjectRequest.builder().bucket(bucket).key(key)
            .metadata(Map.of("mk1", "mv1"));

    PutObjectRequest putObjectRequest = putObjectRequestBuilder.build();
    PutObjectPresignRequest request = PutObjectPresignRequest.builder().putObjectRequest(putObjectRequest)
            .signatureDuration(Duration.ofMinutes(1)).build();

    PresignedPutObjectRequest presignPutObject = s3Presigner.presignPutObject(request);
    URL signedPutURL = presignPutObject.url();

    log.info("Push Presigned URL created: [{}]", signedPutURL.toString());

    return signedPutURL;
}

完整错误响应

<Error>
    <Code>SignatureDoesNotMatch</Code>
    <Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>
    <AWSAccessKeyId>AKIAQ3EGWRZYSIU7ENEO</AWSAccessKeyId>
    <StringToSign>AWS4-HMAC-SHA256
20240402T122245Z
20240402/eu-west-1/s3/aws4_request
66cdf5260d90912bebfd2cc337f5c1bcfb8fb6b4847852bd427627f82bf9b8c8</StringToSign>
    <SignatureProvided>bd7e26bf661eea50966733816872544a6bf75151e30f819f2239725fcae08203</SignatureProvided>
    <StringToSignBytes>41 57 53 34 2d 48 4d 41 43 2d 53 48 41 32 35 36 0a 32 30 32 34 30 34 30 32 54 31 32 32 32 34 35 5a 0a 32 30 32 34 30 34 30 32 2f 65 75 2d 77 65 73 74 2d 31 2f 73 33 2f 61 77 73 34 5f 72 65 71 75 65 73 74 0a 36 36 63 64 66 35 32 36 30 64 39 30 39 31 32 62 65 62 66 64 32 63 63 33 33 37 66 35 63 31 62 63 66 62 38 66 62 36 62 34 38 34 37 38 35 32 62 64 34 32 37 36 32 37 66 38 32 62 66 39 62 38 63 38</StringToSignBytes>
    <CanonicalRequest>PUT
/espaidoc-des/1117beac-c2b4-414a-a518-1c4ac805644d
X-Amz-Algorithm=AWS4-HMAC-SHA256&amp;X-Amz-Credential=AKIAQ3EGWRZYSIU7ENEO%2F20240402%2Feu-west-1%2Fs3%2Faws4_request&amp;X-Amz-Date=20240402T122245Z&amp;X-Amz-Expires=600&amp;X-Amz-SignedHeaders=host%3Bx-amz-meta-mk1
host:s3.eu-west-1.amazonaws.com
x-amz-meta-mk1:

host;x-amz-meta-mk1
UNSIGNED-PAYLOAD</CanonicalRequest>
    <CanonicalRequestBytes>50 55 54 0a 2f 65 73 70 61 69 64 6f 63 2d 64 65 73 2f 31 31 31 37 62 65 61 63 2d 63 32 62 34 2d 34 31 34 61 2d 61 35 31 38 2d 31 63 34 61 63 38 30 35 36 34 34 64 0a 58 2d 41 6d 7a 2d 41 6c 67 6f 72 69 74 68 6d 3d 41 57 53 34 2d 48 4d 41 43 2d 53 48 41 32 35 36 26 58 2d 41 6d 7a 2d 43 72 65 64 65 6e 74 69 61 6c 3d 41 4b 49 41 51 33 45 47 57 52 5a 59 53 49 55 37 45 4e 45 4f 25 32 46 32 30 32 34 30 34 30 32 25 32 46 65 75 2d 77 65 73 74 2d 31 25 32 46 73 33 25 32 46 61 77 73 34 5f 72 65 71 75 65 73 74 26 58 2d 41 6d 7a 2d 44 61 74 65 3d 32 30 32 34 30 34 30 32 54 31 32 32 32 34 35 5a 26 58 2d 41 6d 7a 2d 45 78 70 69 72 65 73 3d 36 30 30 26 58 2d 41 6d 7a 2d 53 69 67 6e 65 64 48 65 61 64 65 72 73 3d 68 6f 73 74 25 33 42 78 2d 61 6d 7a 2d 6d 65 74 61 2d 6d 6b 31 0a 68 6f 73 74 3a 73 33 2e 65 75 2d 77 65 73 74 2d 31 2e 61 6d 61 7a 6f 6e 61 77 73 2e 63 6f 6d 0a 78 2d 61 6d 7a 2d 6d 65 74 61 2d 6d 6b 31 3a 0a 0a 68 6f 73 74 3b 78 2d 61 6d 7a 2d 6d 65 74 61 2d 6d 6b 31 0a 55 4e 53 49 47 4e 45 44 2d 50 41 59 4c 4f 41 44</CanonicalRequestBytes>
    <RequestId>6Q3P82ZWPWNAC5V0</RequestId>
    <HostId>uEVaiZU1gKj0n6KNIrkuWHELwJD9El/DdQ1uKu+o5dwsEvoFdaVTv/gL0e6AfbN/kthrJlo0+9A=</HostId>
</Error>

使用的curl命令

curl --request PUT --header 'Content-Type:' --data-binary '@hurl/push-document/lorem.txt' 'https://s3.eu-west-1.amazonaws.com/espaidoc-des/54c07cd8-1bce-43b9-ab32-28a7e9108c19?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20240402T123532Z&X-Amz-SignedHeaders=host%3Bx-amz-meta-mk1&X-Amz-Expires=60&X-Amz-Credential=AKIAQ3EGWRZYSIU7ENEO%2F20240402%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Signature=ebfbbcfbbaadae7b580ed0a6cddb503371a6aa11b59e229fcc5663225f45a9be'

解决思路

从错误返回的CanonicalRequest可以看出,签名校验时包含了x-amz-meta-mk1请求头,但该头的值为空——这是因为生成预签名URL时指定了元数据,但请求时没有携带对应的元数据头,导致签名校验不通过。

具体修复步骤

  1. 请求时必须携带匹配的元数据头:在curl命令中添加x-amz-meta-mk1: mv1头,确保和预签名URL生成时的元数据完全一致。修改后的curl命令:
curl --request PUT --header 'Content-Type:' --header 'x-amz-meta-mk1: mv1' --data-binary '@hurl/push-document/lorem.txt' 'https://s3.eu-west-1.amazonaws.com/espaidoc-des/54c07cd8-1bce-43b9-ab32-28a7e9108c19?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20240402T123532Z&X-Amz-SignedHeaders=host%3Bx-amz-meta-mk1&X-Amz-Expires=60&X-Amz-Credential=AKIAQ3EGWRZYSIU7ENEO%2F20240402%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Signature=ebfbbcfbbaadae7b580ed0a6cddb503371a6aa11b59e229fcc5663225f45a9be'
  1. 验证签名头的一致性:预签名URL的X-Amz-SignedHeaders包含host和x-amz-meta-mk1,所以请求时必须携带这两个头(host头curl会自动添加,无需手动指定,但x-amz-meta-mk1必须显式添加)。

  2. 可选:解除元数据与签名的绑定:如果不需要固定元数据,可以在生成预签名URL时,不将元数据放入PutObjectRequest的metadata中,让请求方上传时自行添加元数据——此时元数据不会被纳入签名校验范围,但这种方式不适合需要强制设置元数据的场景。


内容的提问来源于stack exchange,提问作者Jordi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 18:59:53