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

Amazon S3 POST对象Signature V4签名计算不符问题求助

AWS Signature V4 for S3 POST Upload: Signature Mismatch Issue

我刚帮你排查了这个问题,核心原因是你错误地使用了Base64编码后的policy字符串来计算签名,但AWS要求的是对原始未编码的JSON policy的UTF-8字节进行HMAC-SHA256运算。

问题细节拆解

官方S3 POST上传示例里的expectedBase64Policy只是原始policy JSON的Base64编码结果,用于在表单中传递给S3;但签名计算的源头必须是解码后的原始JSON内容。你当前的代码直接把Base64字符串传给HmacSHA256方法,这就导致最终签名和预期值完全不符。

而你提到通用测试用例能正常匹配,是因为那个测试场景不需要处理Base64编码的输入,所有参数都是直接的明文字符串,所以密钥生成流程完全正确。

修正后的代码示例

只需要在计算签名前,先把Base64编码的policy解码为原始JSON,再用它的UTF-8字节进行签名计算:

public static void test() {
    try {
        String expectedBase64Policy = "eyAiZXhwaXJhdGlvbiI6ICIyMDE1LTEyLTMwVDEyOjAwOjAwLjAwMFoiLA0KICAiY29uZGl0aW9ucyI6IFsNCiAgICB7ImJ1Y2tldCI6ICJzaWd2NGV4YW1wbGVidWNrZXQifSwNCiAgICBbInN0YXJ0cy13aXRoIiwgIiRrZXkiLCAidXNlci91c2VyMS8iXSwNCiAgICB7ImFjbCI6ICJwdWJsaWMtcmVhZCJ9LA0KICAgIHsic3VjY2Vzc19hY3Rpb25fcmVkaXJlY3QiOiAiaHR0cDovL3NpZ3Y0ZXhhbXBsZWJ1Y2tldC5zMy5hbWF6b25hd3MuY29tL3N1Y2Nlc3NmdWxfdXBsb2FkLmh0bWwifSwNCiAgICBbInN0YXJ0cy13aXRoIiwgIiRDb250ZW50LVR5cGUiLCAiaW1hZ2UvIl0sDQogICAgeyJ4LWFtei1tZXRhLXV1aWQiOiAiMTQzNjUxMjM2NTEyNzQifSwNCiAgICB7IngtYW16LXNlcnZlci1zaWRlLWVuY3J5cHRpb24iOiAiQUVTMjU2In0sDQogICAgWyJzdGFydHMtd2l0aCIsICIkeC1hbXotbWV0YS10YWciLCAiIl0sDQoNCiAgICB7IngtYW16LWNyZWRlbnRpYWwiOiAiQUtJQUlPU0ZPRE5ON0VYQU1QTEUvMjAxNTEyMjkvdXMtZWFzdC0xL3MzL2F3czRfcmVxdWVzdCJ9LA0KICAgIHsieC1hbXotYWxnb3JpdGhtIjogIkFXUzQtSE1BQy1TSEEyNTYifSwNCiAgICB7IngtYW16LWRhdGUiOiAiMjAxNTEyMjlUMDAwMDAwWiIgfQ0KICBdDQp9";
        String expectedSignature = "46503978d3596de22955b4b18d6dfb1d54e8c5958727d5bdcd02cc1119c60fc9";
        String secretKey = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY";
        
        // 关键修正:解码Base64得到原始policy JSON
        byte[] decodedPolicyBytes = DatatypeConverter.parseBase64Binary(expectedBase64Policy);
        String rawPolicy = new String(decodedPolicyBytes, "UTF8");
        
        byte[] signingKey = getSignatureKey(secretKey, "20151229", "us-east-1", "s3", false);
        // 使用原始policy的UTF-8字节计算签名
        byte[] signedPolicy = HmacSHA256(rawPolicy, signingKey);
        String calculatedSignature = DatatypeConverter.printHexBinary(signedPolicy)
                .toLowerCase();
        
        System.out.println("Generating signature for policy string for POST object");
        System.out.println("EXP: " + expectedSignature);
        System.out.println("GOT: " + calculatedSignature);
        
        // 通用测试用例部分保留不变
        System.out.println("Generating signing for test example");
        getSignatureKey("wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY", "20120215", "us-east-1", "iam", true);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

额外检查点

修正后你会发现签名和预期完全匹配,再补充几个后续开发中需要注意的细节:

  • 确保所有字符串编码统一使用UTF-8,你的代码里已经正确指定了"UTF8",这部分没问题
  • 确认签名密钥生成时的日期、区域、服务名,必须和policy中x-amz-date、x-amz-credential字段的对应部分完全一致
  • 如果后续自定义policy,要注意JSON格式的正确性(比如引号、逗号不能遗漏),否则即使签名正确,S3也会拒绝请求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 03:57:50