java S3例外情况:我们计算的请求签名与您提供的签名不匹配

vuktfyat  于 2023-01-01  发布在  Java
关注(0)|答案(2)|浏览(141)

我有不同的对象生成文件保存在S3中。每个对象调用以下函数来保存文件。
我有以下问题,只有少数对象。对象要么总是保存文件,要么永远不能保存文件。

/**
     * Upload a file (with metadata).
     *
     * @param bucketId    the id of the bucket
     * @param key         the key of the file
     * @param inputStream the content of the file
     * @param metadata    the metadata of the file
     * @return the eTag of the uploaded file
     * @throws IOException If an error occurs during the file upload
     */
    public String upload(String bucketId, String key, InputStream inputStream, Map<String, String> metadata) throws IOException {
        LOG.info("Upload file {} on bucket {} with metadata: {}", key, bucketId, metadata);
        CreateMultipartUploadRequest.Builder builder = CreateMultipartUploadRequest.builder();
        if (!this.encryptionAlgorithm.equalsIgnoreCase("none")) {
            builder = builder.serverSideEncryption(this.encryptionAlgorithm);
        }
        CreateMultipartUploadRequest createMultipartUploadRequest = builder.bucket(bucketId)
            .key(key)
            .metadata(metadata)
            .build();

        CreateMultipartUploadResponse createMultipartUploadResponse = s3Client.createMultipartUpload(createMultipartUploadRequest);
        String uploadId = createMultipartUploadResponse.uploadId();

        try {
            List<CompletedPart> parts = uploadFileParts(bucketId, key, uploadId, inputStream);

            CompleteMultipartUploadRequest completeMultipartUploadRequest = CompleteMultipartUploadRequest.builder()
                .bucket(bucketId)
                .key(key)
                .uploadId(uploadId)
                .multipartUpload(CompletedMultipartUpload.builder().parts(parts).build())
                .build();
            CompleteMultipartUploadResponse completeMultipartUploadResponse = s3Client.completeMultipartUpload(completeMultipartUploadRequest);

            return completeMultipartUploadResponse.eTag();
        } catch (Exception e) {
            LOG.error("Error while uploading {} multipart {} on bucket {} with metadata {}", key, uploadId, bucketId, metadata, e);

            s3Client.abortMultipartUpload(AbortMultipartUploadRequest.builder()
                .bucket(bucketId)
                .key(key)
                .uploadId(uploadId)
                .build());

            throw e;
        }
    }

错误是

    • 我们计算的请求签名与您提供的签名不匹配。请检查您的AWS保密访问密钥和签名方法。有关详细信息,请参阅REST身份验证和SOAP身份验证。(服务:S3,状态代码:403,请求ID:79b6c0a2 - 0d74 - 1f30-a4bf-246e9631ccd8,扩展请求编号:无效)**

我验证了,bucket始终是相同的值,输入流数据包含文件的数据,数据成功传输到S3 bucket,key始终是eventsnapshot-21234-7-2021-08-12-1628767690000.jpg
你已经有这样的问题了吗?

kr98yfug

kr98yfug1#

我发现了这个问题。如果元数据值末尾有白色,那么AWS SDK生成的签名将与服务器返回的签名不同。
可能是S3修剪了元数据名称和值。
后来我在aws-sdk-go中也发现了类似的问题:https://github.com/aws/aws-sdk-go/issues/2448
我使用的是aws-sdk-java的2.15.36版本。我不知道它是否在新版本的SDK中得到了修复。

jchrr9hc

jchrr9hc2#

对我来说,这个问题是当文件名包含特殊字符(如©)时引起的。我将文件名设置为S3 Object的元数据。为了解决这个问题,我从文件名中删除了这些特殊字符。

参考链接:

用户定义的元数据是一组键值对。Amazon S3以小写形式存储用户定义的元数据键。Amazon S3允许在元数据值中使用任意Unicode字符。为避免出现与这些元数据值的表示有关的问题,在使用REST时应遵守使用US-ASCII字符的规定,在通过POST使用SOAP或基于浏览器的上载时应遵守UTF-8的规定。在元数据值中使用非US-ASCII字符时,将检查提供的Unicode字符串是否包含非US-ASCII字符。此类标头的值在存储之前按照RFC 2047进行字符解码,并在返回之前按照RFC 2047进行编码以使其成为邮件安全的。如果字符串仅包含US-ASCII字符,则按原样显示。

我的环境:

  • Spring Boot:2.6.6
  • aws-java-软件开发包-s3:1.12.131
  • HTTP客户端:4.5.13

相关问题