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

访问Amazon SQS时如何自动刷新过期的AWS STS临时安全凭证?

STS临时凭证访问SQS自动刷新解决方案

问题根因

你当前的配置会出现过期报错是两个原因导致的:

  • 使用了AWSStaticCredentialsProvider,这个实现类只会持有初始化时传入的固定凭证,不会主动更新
  • 相关Bean都是默认单例,启动时初始化一次后就不会重新创建,凭证过期后没有机制更新

最优解决方案(推荐)

直接使用AWS SDK原生提供的STSAssumeRoleSessionCredentialsProvider,无需自己实现凭证刷新逻辑,SDK会自动在凭证快过期时调用STS接口获取新凭证。

修改后的配置代码如下,可直接替换你现有的两套配置:

@Configuration
@Slf4j
public class QueueConfig {

    @Value("${aws.sts.role-arn:XXXX}")
    private String roleArn;
    @Value("${aws.sts.role-session-name:XXX}")
    private String roleSessionName;
    @Value("${aws.region:us-west-1}")
    private String region;

    @Bean
    public QueueMessagingTemplate queueMessagingTemplate(AmazonSQSAsync amazonSQSAsync) {
        log.info("queueMessagingTemplate init");
        return new QueueMessagingTemplate(amazonSQSAsync);
    }

    @Bean
    @Primary
    public AmazonSQSAsync amazonSQSAsync() {
        // 初始化支持自动刷新的STS凭证提供器
        STSAssumeRoleSessionCredentialsProvider credentialsProvider = 
                new STSAssumeRoleSessionCredentialsProvider.Builder(roleArn, roleSessionName)
                .withStsClient(AmazonSTSClientBuilder.standard().withRegion(region).build())
                // 可选配置:会话有效期,最大可设12小时,需要和角色的最大会话时长配置匹配
                .withSessionDurationSeconds(3600)
                .build();

        return AmazonSQSAsyncClientBuilder
                .standard()
                .withRegion(region)
                // 替换原来的静态凭证提供器
                .withCredentials(credentialsProvider)
                .build();
    }
}

如果你使用的是AWS SDK V2,对应自动刷新凭证的类为StsAssumeRoleCredentialsProvider,使用逻辑完全一致。

自定义刷新方案(特殊场景用)

如果你有自定义的STS调用逻辑,不能直接用SDK自带的提供器,可以自行实现凭证刷新逻辑,示例如下:

  1. 实现自动刷新的凭证提供器
@Component
@Slf4j
public class AutoRefreshStsCredentialsProvider implements AWSCredentialsProvider {
    private BasicSessionCredentials currentCredentials;
    private Instant expirationTime;
    // 提前5分钟刷新凭证,避免过期
    private static final Duration REFRESH_AHEAD_TIME = Duration.ofMinutes(5);
    private static final String ROLE_ARN = "XXXX";
    private static final String ROLE_SESSION_NAME = "XXX";
    private static final Region REGION = Region.US_WEST_1;

    @Override
    public AWSCredentials getCredentials() {
        if (currentCredentials == null || Instant.now().isAfter(expirationTime.minus(REFRESH_AHEAD_TIME))) {
            refreshCredentials();
        }
        return currentCredentials;
    }

    private synchronized void refreshCredentials() {
        // 双重检查避免多线程重复刷新
        if (currentCredentials != null && !Instant.now().isAfter(expirationTime.minus(REFRESH_AHEAD_TIME))) {
            return;
        }
        try (StsClient stsClient = StsClient.builder().region(REGION).build()) {
            AssumeRoleRequest roleRequest = AssumeRoleRequest.builder()
                    .roleArn(ROLE_ARN)
                    .roleSessionName(ROLE_SESSION_NAME)
                    .build();
            AssumeRoleResponse roleResponse = stsClient.assumeRole(roleRequest);
            Credentials newCreds = roleResponse.credentials();
            this.currentCredentials = new BasicSessionCredentials(
                    newCreds.accessKeyId(),
                    newCreds.secretAccessKey(),
                    newCreds.sessionToken()
            );
            this.expirationTime = newCreds.expiration();
        } catch (StsException e) {
            log.error("STS凭证刷新失败", e);
            // 刷新失败时如果旧凭证还未过期,继续使用旧凭证,避免业务直接报错
            if (currentCredentials == null || Instant.now().isAfter(expirationTime)) {
                throw new RuntimeException("无有效可用的STS凭证", e);
            }
        }
    }

    @Override
    public void refresh() {
        refreshCredentials();
    }
}
  1. 将自定义提供器注入SQS客户端
@Bean
@Primary
public AmazonSQSAsync amazonSQSAsync(AutoRefreshStsCredentialsProvider credentialsProvider) {
        return AmazonSQSAsyncClientBuilder
                .standard()
                .withRegion(Regions.US_WEST_1)
                .withCredentials(credentialsProvider)
                .build();
}

注意事项

  • 不要使用AWSStaticCredentialsProvider承载临时STS凭证,这个类仅适合长期不变的AKSK场景
  • 若项目中多个AWS服务共用同一个STS角色,可以把凭证提供器抽为公共Bean复用,避免重复调用STS接口
  • 生产环境建议将角色ARN、区域、会话名等配置放到配置文件中,不要硬编码在代码里

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 11:15:03