小厂程序员

自由自在,无忧无虑

Requests that are pre-signed by SigV4 algorithm are valid for at least 1 second and at most 7 days. The expiration duration set on the current request [PT2073600H] does not meet these bounds.

内容目录

你遇到的这个错误是因为使用 SigV4 算法预签名的请求,其过期时长设置为 PT2073600H(换算下来远超过 7 天),违反了 SigV4 预签名请求的有效期规则——最短 1 秒,最长 7 天

错误根源解析

  1. 时间格式含义PT2073600H 是 ISO 8601 时间格式,PT 表示“时间持续期”,2073600H 表示 2073600 小时(约 236 年),远超出 SigV4 规定的 7 天(604800 秒)上限;
  2. SigV4 核心规则:AWS/兼容 SigV4 的服务(如 S3、SQS 等)明确要求,预签名 URL/请求的有效期必须满足 1秒 ≤ 有效期 ≤ 7天,超出这个范围会直接抛出该异常。

解决方案(以 Java 为例,适配常见的 AWS SDK v2)

1. 核心修复:设置合法的过期时长

将过期时长调整为 7 天内(推荐 1 小时~7 天,根据业务需求),以下是完整的 SigV4 预签名请求示例(以 S3 为例):

import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.presigner.S3Presigner;
import software.amazon.awssdk.services.s3.presigner.model.GetObjectPresignRequest;
import software.amazon.awssdk.services.s3.presigner.model.PresignedGetObjectRequest;

import java.time.Duration;

public class SigV4PresignExample {

    public static void main(String[] args) {
        // 1. 配置区域和凭证(根据你的实际环境调整)
        Region region = Region.US_EAST_1;
        S3Presigner presigner = S3Presigner.builder()
                .region(region)
                .credentialsProvider(DefaultCredentialsProvider.create())
                .build();

        try {
            // 2. 构建预签名请求,设置合法的过期时长(示例:2小时,≤7天)
            GetObjectPresignRequest presignRequest = GetObjectPresignRequest.builder()
                    .signatureDuration(Duration.ofHours(2)) // 核心修复:替换为 ≤7天的时长
                    .getObjectRequest(builder -> builder
                            .bucket("your-bucket-name")
                            .key("your-object-key"))
                    .build();

            // 3. 生成预签名URL
            PresignedGetObjectRequest presignedRequest = presigner.presignGetObject(presignRequest);
            System.out.println("预签名URL: " + presignedRequest.url());

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            presigner.close();
        }
    }
}

2. 不同场景的过期时长设置示例

场景 合法的 Duration 设置 说明
短期有效(1小时) Duration.ofHours(1) 推荐用于敏感操作
中期有效(1天) Duration.ofDays(1) 常规业务使用
最长有效(7天) Duration.ofDays(7) 不建议超过,符合 SigV4 上限
最短有效(1秒) Duration.ofSeconds(1) 仅测试用,实际很少使用

3. 错误时长的修正(针对 PT2073600H

如果你是通过字符串解析时长(如 PT2073600H),需要先修正字符串,再转换为 Duration:

// 错误的时长字符串
String invalidExpiry = "PT2073600H";
// 修正为合法的时长(比如7天)
String validExpiry = "PT168H"; // 7天 = 168小时
// 解析为Duration
Duration expiryDuration = Duration.parse(validExpiry);

4. 适配 AWS SDK v1 的修复示例

如果使用旧版 SDK v1,设置方式略有不同,但核心是控制过期时间在 7 天内:

import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest;

import java.net.URL;
import java.util.Date;

public class SigV4PresignV1Example {

    public static void main(String[] args) {
        String accessKey = "your-access-key";
        String secretKey = "your-secret-key";
        String bucketName = "your-bucket-name";
        String objectKey = "your-object-key";

        AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
                .withRegion(Regions.US_EAST_1)
                .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKey, secretKey)))
                .build();

        // 计算过期时间:当前时间 + 2小时(≤7天)
        Date expiration = new Date();
        long expTimeMillis = expiration.getTime();
        expTimeMillis += 2 * 60 * 60 * 1000; // 2小时 = 2*60*60*1000毫秒
        expiration.setTime(expTimeMillis);

        // 生成预签名URL
        GeneratePresignedUrlRequest generatePresignedUrlRequest =
                new GeneratePresignedUrlRequest(bucketName, objectKey)
                        .withExpiration(expiration);
        URL presignedUrl = s3Client.generatePresignedUrl(generatePresignedUrlRequest);

        System.out.println("预签名URL: " + presignedUrl.toString());
    }
}

关键注意事项

  1. 时间单位换算:7 天 = 604800 秒 = 168 小时,设置时不要超过这个值;
  2. ISO 8601 格式规范
    • 正确格式:PT1H(1小时)、PT2D(2天)、PT30M(30分钟);
    • 错误格式:P2073600H(缺少 T)、PT7D 是合法的(7天);
  3. 业务适配:如果你的业务需要超过 7 天的有效链接,不要使用预签名 URL,可改用“临时凭证 + 客户端直接请求”的方式;
  4. 验证方式:生成预签名 URL 后,可直接访问测试,若仍报错需检查:
    • 时长是否真的 ≤7 天;
    • 凭证是否有效;
    • 服务端是否开启 SigV4 验证。

总结

  1. 核心修复:将 SigV4 预签名请求的过期时长调整为 1秒 ~ 7天 范围内(推荐用 Duration.ofHours()/Duration.ofDays() 设置);
  2. 格式修正:确保 ISO 8601 时长字符串符合规范(如 PT168H 表示7天);
  3. 替代方案:若业务需要超过7天的有效链接,放弃预签名 URL,改用临时访问凭证。
Requests that are pre-signed by SigV4 algorithm are valid for at least 1 second and at most 7 days. The expiration duration set on the current request [PT2073600H] does not meet these bounds.

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

Scroll to top