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

LocalStack环境下AWS S3预签名GET URL报InvalidAccessKeyId错误

问题描述

在LocalStack本地AWS环境中,普通的S3上传、下载图片功能正常,但使用带有效期的预签名URL(Presigned URLs)实现下载时,点击生成的URL会返回以下错误:

<Error>
<Code>InvalidAccessKeyId</Code>
   <Message>
      The AWS Access Key Id you provided does not exist in our records.
   </Message>
<AWSAccessKeyId>test</AWSAccessKeyId>
</Error>

生成预签名URL的代码如下:

protected URL generatePresignedURL(String objectKey) {

    // object key example: "Screen Shot 2022-07-04 at 11.29.59 PM (3).png"

    S3Presigner presigner = S3Presigner.create();

    GetObjectRequest objectRequest = buildGetRequest(objectKey);
    GetObjectPresignRequest presignedRequest = buildPresignedGetRequest(objectRequest);

    PresignedGetObjectRequest presignedGetObjectRequest =
            presigner.presignGetObject(presignedRequest);

    System.out.println("Presigned URL: " + presignedGetObjectRequest.url());


    return presignedGetObjectRequest.url();
}


protected GetObjectRequest buildGetRequest(String objectKey) {
    return GetObjectRequest.builder()
            .bucket(bucketName)
            .key(objectKey)
            .build();
}


protected GetObjectPresignRequest buildPresignedGetRequest(GetObjectRequest objectRequest) {

    // Create a GetObjectPresignRequest from a GetObjectRequest to specify the signature duration
    return GetObjectPresignRequest.builder()
            .signatureDuration(Duration.ofMinutes(5))
            .getObjectRequest(objectRequest)
            .build();
}

Docker Compose中LocalStack的S3配置:

s3-local:
    container_name: "s3-local"
    image: localstack/localstack
    ports:
      - "127.0.0.1:8008:4566"            # LocalStack Gateway
    environment:
      - SERVICES=s3
      - AWS_ACCESS_KEY_ID=test
      - AWS_SECRET_ACCESS_KEY=test
      - START_WEB=0
      - DEBUG=0

创建S3桶的命令:

aws s3 mb s3://$LOCAL_S3_BUCKET_NAME --endpoint-url=$LOCAL_S3_SERVICE_ENDPOINT

请问是否需要对S3Presigner对象进行额外配置?


解决方案

需要对S3Presigner进行额外配置,适配LocalStack的本地环境,具体调整如下:

  • 指定LocalStack端点与区域
    默认S3Presigner会连接AWS官方S3服务,必须显式配置LocalStack的端点URL(如http://localhost:8008),同时指定一个有效区域(LocalStack对区域要求宽松,比如us-east-1即可)。

  • 配置匹配的凭证提供者
    虽然LocalStack允许任意凭证,但需确保S3Presigner使用的凭证与LocalStack配置的test/test一致,避免签名验证失败。

修改后的生成预签名URL方法示例:

protected URL generatePresignedURL(String objectKey) {
    // 配置LocalStack端点和区域
    S3ClientConfiguration clientConfig = S3ClientConfiguration.builder()
            .endpointOverride(URI.create("http://localhost:8008"))
            .region(Region.US_EAST_1)
            .build();

    // 配置凭证
    AwsCredentials credentials = AwsBasicCredentials.create("test", "test");
    AwsCredentialsProvider credentialsProvider = StaticCredentialsProvider.create(credentials);

    // 创建配置好的S3Presigner
    S3Presigner presigner = S3Presigner.builder()
            .credentialsProvider(credentialsProvider)
            .clientConfiguration(clientConfig)
            .build();

    GetObjectRequest objectRequest = buildGetRequest(objectKey);
    GetObjectPresignRequest presignedRequest = buildPresignedGetRequest(objectRequest);

    PresignedGetObjectRequest presignedGetObjectRequest =
            presigner.presignGetObject(presignedRequest);

    System.out.println("Presigned URL: " + presignedGetObjectRequest.url());

    return presignedGetObjectRequest.url();
}
  • 额外注意事项
    1. 若LocalStack端点不是localhost:8008,替换为实际的$LOCAL_S3_SERVICE_ENDPOINT值;
    2. 确保生成预签名URL时使用的桶名与创建的桶名完全一致;
    3. LocalStack的S3处理预签名URL时,要求客户端签名时使用匹配的端点,否则会触发凭证验证错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 03:54:11