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

S3预签名URL部署一段时间后持续提示令牌过期问题排查

解决Spring Boot 3中S3预签名URL生成时“提供的令牌已过期”问题

问题背景

服务基于Spring Boot 3开发,使用EKS服务账户的Web Identity Token获取STS凭证生成S3预签名URL。刚部署时功能正常,但运行一段时间后持续抛出“提供的令牌已过期”错误。

原生成代码:

private URL generatePreSignedUrl(String s3Key, String s3Bucket, Date expiration, HttpMethod method) {
        GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(s3Bucket, s3Key)
                .withMethod(method)
                .withExpiration(expiration);
        return amazonS3.generatePresignedUrl(generatePresignedUrlRequest);
    }

原配置:

spring:
 cloud:
    aws:
      credentials:
        sts:
          web-identity-token-file: /var/run/secrets/eks.amazonaws.com/serviceaccount/token

cloud:
  aws:
    region:
       static: us-east-1
    stack:
      auto: false
    credentials:
      use-default-aws-credentials-chain: true

问题根源

  1. 配置冲突:spring.cloud.aws和cloud.aws混合使用,Spring Cloud AWS 3.x(适配Spring Boot 3)仅识别spring.cloud.aws前缀的配置,导致部分凭证配置未生效。
  2. 旧SDK客户端限制:使用的AmazonS3是AWS SDK v1的客户端,它不会自动刷新过期的STS临时凭证。EKS服务账户令牌对应的STS凭证有默认1小时的有效期,过期后客户端无法自动获取新凭证,从而报错。

解决方案

1. 统一并修正配置

删除cloud.aws前缀的配置,统一使用spring.cloud.aws,确保STS凭证自动刷新的配置生效:

spring:
  cloud:
    aws:
      region:
        static: us-east-1
      stack:
        auto: false
      credentials:
        sts:
          web-identity-token-file: /var/run/secrets/eks.amazonaws.com/serviceaccount/token
          role-arn: # 替换为你的EKS服务账户关联的IAM角色ARN,必须配置
      s3:
        endpoint: # 可选,若使用S3兼容存储或特定区域端点可配置

注意:必须配置role-arn,否则STS无法正确获取临时凭证。

2. 切换到AWS SDK v2的S3客户端

Spring Cloud AWS 3.x推荐使用AWS SDK v2的客户端,它会自动处理临时凭证的刷新。

Maven依赖示例:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-aws-s3</artifactId>
    <version>3.2.1</version> <!-- 适配Spring Boot 3.x的最新版本 -->
</dependency>

3. 修改预签名URL生成代码

使用AWS SDK v2的S3Presigner来生成预签名URL,它会自动使用刷新后的凭证:

import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
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.PutObjectPresignRequest;
import java.net.URL;
import java.time.Duration;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;

@Service
public class S3Service {

    private final S3Presigner s3Presigner;

    // 构造函数注入S3Presigner,Spring Cloud AWS会自动配置
    public S3Service(S3Presigner s3Presigner) {
        this.s3Presigner = s3Presigner;
    }

    public URL generatePreSignedUrl(String s3Key, String s3Bucket, Duration expiration, HttpMethod method) {
        if (HttpMethod.GET.equals(method)) {
            GetObjectRequest getObjectRequest = GetObjectRequest.builder()
                    .bucket(s3Bucket)
                    .key(s3Key)
                    .build();

            GetObjectPresignRequest presignRequest = GetObjectPresignRequest.builder()
                    .signatureDuration(expiration)
                    .getObjectRequest(getObjectRequest)
                    .build();

            return s3Presigner.presignGetObject(presignRequest).url();
        } else if (HttpMethod.PUT.equals(method)) {
            PutObjectRequest putObjectRequest = PutObjectRequest.builder()
                    .bucket(s3Bucket)
                    .key(s3Key)
                    .build();

            PutObjectPresignRequest presignRequest = PutObjectPresignRequest.builder()
                    .signatureDuration(expiration)
                    .putObjectRequest(putObjectRequest)
                    .build();

            return s3Presigner.presignPutObject(presignRequest).url();
        }
        // 可扩展其他HTTP方法
        throw new IllegalArgumentException("Unsupported HTTP method: " + method);
    }
}

4. 验证凭证刷新机制

AWS SDK v2的S3Presigner会自动使用Spring Cloud AWS配置的凭证提供者,该提供者会定期检查STS凭证的有效期,在过期前自动获取新的临时凭证,无需手动干预。

额外注意事项

  • 确保EKS服务账户已正确关联IAM角色,且角色拥有生成S3预签名URL所需的权限(如s3:GetObject、s3:PutObject等)。
  • 若需要自定义STS凭证有效期,可在配置中添加spring.cloud.aws.credentials.sts.session-duration设置(单位:秒,默认3600秒)。

内容的提问来源于stack exchange,提问作者Ahmad M AbuGhozeh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 22:26:32