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

Spring Boot集成Localstack SQS遇无效安全令牌错误求助

问题描述

我正在开发一个基于Spring Boot 2.7.9的Kotlin应用(运行于Windows平台),用于记录SQS队列消息。启动应用时触发无效安全令牌错误,但通过Docker Compose启动Localstack后,可使用AWS CLI正常创建主题、队列、订阅,也能发送接收消息。期望实现向SQS发消息时应用记录消息,同时尝试用Test Container搭建测试环境,不清楚是Docker Compose还是Spring Boot配置有误,请求排查问题。

错误信息

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'simpleMessageListenerContainer' defined in class path resource [org/springframework/cloud/aws/messaging/config/annotation/SqsConfiguration.class]: Invocation of init method failed; nested exception is com.amazonaws.services.sqs.model.AmazonSQSException: The security token included in the request is invalid. (Service: AmazonSQS; Status Code: 403; Error Code: InvalidClientTokenId; Request ID: 4cb154fc-3a61-58ca-aeea-086c2e52e235; Proxy: null)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1804) ~[spring-beans-5.3.25.jar:5.3.25]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620) ~[spring-beans-5.3.25.jar:5.3.25]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.25.jar:5.3.25]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.25.jar:5.3.25]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.25.jar:5.3.25]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.25.jar:5.3.25]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.25.jar:5.3.25]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955) ~[spring-beans-5.3.25.jar:5.3.25]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.25.jar:5.3.25]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.25.jar:5.3.25]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) ~[spring-boot-2.7.9.jar:2.7.9]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:731) ~[spring-boot-2.7.9.jar:2.7.9]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) ~[spring-boot-2.7.9.jar:2.7.9]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) ~[spring-boot-2.7.9.jar:2.7.9]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1303) ~[spring-boot-2.7.9.jar:2.7.9]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1292) ~[spring-boot-2.7.9.jar:2.7.9]
    at com.example.demo.DemoApplicationKt.main(DemoApplication.kt:20) ~[main/:na]
问题排查与解决

核心问题定位

CLI能正常访问Localstack但应用报错,说明问题出在Spring Boot的AWS客户端配置:

  • 未指定Localstack端点:当前配置的AmazonSQSAsync客户端默认请求AWS官方服务,而非本地Localstack,官方服务不认可dummy凭证导致验证失败
  • 客户端实例未被Spring管理:amazonSQSAsync()方法未加@Bean注解,Spring Cloud AWS的自动配置组件可能未使用自定义客户端

修复步骤

1. 修改SQS配置类

添加Localstack端点配置,并修正Bean声明:

package com.example.demo

import com.amazonaws.auth.AWSCredentials
import com.amazonaws.auth.AWSStaticCredentialsProvider
import com.amazonaws.auth.BasicAWSCredentials
import com.amazonaws.client.builder.AwsClientBuilder
import com.amazonaws.regions.Regions
import com.amazonaws.services.sqs.AmazonSQSAsync
import com.amazonaws.services.sqs.AmazonSQSAsyncClientBuilder
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.cloud.aws.messaging.config.SimpleMessageListenerContainerFactory
import org.springframework.cloud.aws.messaging.config.annotation.EnableSqs
import org.springframework.cloud.aws.messaging.core.QueueMessagingTemplate
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import javax.annotation.PostConstruct

@Configuration
@EnableSqs
class SqsConfiguration {
    private val logger: Logger = LoggerFactory.getLogger(SqsConfiguration::class.java)
    
    @Bean
    fun credentials(): AWSCredentials {
        return BasicAWSCredentials("dummy", "dummy")
    }

    @Bean // 关键:让Spring管理此客户端实例
    fun amazonSQSAsync(): AmazonSQSAsync {
        return AmazonSQSAsyncClientBuilder.standard()
            .withEndpointConfiguration(
                AwsClientBuilder.EndpointConfiguration(
                    "http://localhost:4566", // 指定Localstack端点
                    Regions.US_EAST_1.name
                )
            )
            .withCredentials(AWSStaticCredentialsProvider(credentials()))
            .build()
    }

    @Bean
    fun queueMessagingTemplate(): QueueMessagingTemplate {
        return QueueMessagingTemplate(amazonSQSAsync())
    }

    @Bean
    fun simpleMessageListenerContainerFactory(): SimpleMessageListenerContainerFactory {
        val msgListenerContainerFactory = SimpleMessageListenerContainerFactory()
        msgListenerContainerFactory.setAmazonSqs(amazonSQSAsync())
        return msgListenerContainerFactory
    }

    @PostConstruct
    fun init() {
        logger.info("SqsConfiguration created")
    }
}

2. 可选:用配置文件灵活配置端点

在src/main/resources/application.yml中添加配置,避免硬编码:

cloud:
  aws:
    region:
      static: us-east-1
    stack:
      auto: false
    sqs:
      endpoint: http://localhost:4566
    credentials:
      access-key: dummy
      secret-key: dummy

此时可简化配置类,仅保留@EnableSqs和必要Bean。

3. 验证消费者队列名称

确保@SqsListener中的队列名称与CLI创建的一致,或使用完整URL:

@SqsListener("http://localhost:4566/000000000000/test-queue")

4. Test Container集成配置

添加Testcontainers依赖到build.gradle:

testImplementation("org.testcontainers:localstack:1.17.6")
testImplementation("org.testcontainers:junit-jupiter:1.17.6")

编写测试类:

package com.example.demo

import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest
import org.testcontainers.containers.localstack.LocalStackContainer
import org.testcontainers.junit.jupiter.Container
import org.testcontainers.junit.jupiter.Testcontainers
import org.testcontainers.utility.DockerImageName

@Testcontainers
@SpringBootTest(properties = [
    "cloud.aws.sqs.endpoint=\${localstack.sqs.endpoint}",
    "cloud.aws.credentials.access-key=dummy",
    "cloud.aws.credentials.secret-key=dummy",
    "cloud.aws.region.static=us-east-1"
])
class SqsIntegrationTest {

    companion object {
        @Container
        val localstack = LocalStackContainer(DockerImageName.parse("localstack/localstack:latest"))
            .withServices(LocalStackContainer.Service.SQS, LocalStackContainer.Service.SNS)

        init {
            System.setProperty("localstack.sqs.endpoint", localstack.getEndpointOverride(LocalStackContainer.Service.SQS).toString())
        }
    }

    @Test
    fun testSqsMessageReceiving() {
        // 编写测试逻辑:发送消息并验证消费者接收
    }
}

验证修复

  1. 重启Localstack和Spring Boot应用
  2. 使用CLI发送消息到SNS主题,检查应用日志是否输出Received message: Hello World

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 20:42:22