SQS ExpiredToken:请求中包含的安全令牌是过期状态代码:403

时间:2016-04-20 01:15:18

标签: java amazon-web-services aws-sdk amazon-sqs

我在EC2上运行一个长时间运行的工作进程,它使用来自SQS队列的项目。过了一段时间(8-12小时,我估计)我开始得到过期的安全令牌错误。我希望aws lib能够自动处理凭证刷新,但似乎并非如此。无论如何在客户端内处理? 仅当我使用DefaultCredentialsProviderChain生成访问时才会发生这种情况。与密钥和密钥一起使用时不会发生此错误。 堆栈跟踪如下:

com.amazonaws.AmazonServiceException: The security token included in the request is expired (Service: AmazonSQS; Status Code: 403; Error Code: ExpiredToken; Request ID: 6ff6e1a0-d668-5ac5-bcd7-ae30058f25c0)
    at com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.java:1182)
    at com.amazonaws.http.AmazonHttpClient.executeOneRequest(AmazonHttpClient.java:770)
    at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:489)
    at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:310)
    at com.amazonaws.services.sqs.AmazonSQSClient.invoke(AmazonSQSClient.java:2419)
    at com.amazonaws.services.sqs.AmazonSQSClient.receiveMessage(AmazonSQSClient.java:1130)
    at com.amazonaws.services.sqs.AmazonSQSAsyncClient$24.call(AmazonSQSAsyncClient.java:1783)
    at com.amazonaws.services.sqs.AmazonSQSAsyncClient$24.call(AmazonSQSAsyncClient.java:1779)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

我发现的解决方法是每次遇到过期的令牌错误时更新awsCredentials并重置sqs客户端。

awsCredentials = (new DefaultAWSCredentialsProviderChain).getCredentials
sqs = SimpleSQSClient(awsCredentials, Regions.US_EAST_1)
queueSQS = sqs.simple(QueueName(queueName), true)

注意:我正在使用包装器kifi/franz

1 个答案:

答案 0 :(得分:8)

AWS软件开发工具包确实能够循环从实例配置文件继承的临时凭证,但是通过在SimpleSQSClient的构造函数中传递显式的AWSCredentials对象,我相信您拒绝这样做的机会。

您没有明确声明您的应用程序正在继承实例角色,但您的帖子中有足够的证据可以推断出这种情况:

  • 您的应用程序在EC2上运行。
  • DefaultAWSCredentialsProviderChain的行为是查找“通过Amazon EC2元数据服务提供的实例配置文件凭据”,如果它找不到其他凭据。
  • 在未明确传递您自己的已知访问/密钥时,您才会看到此行为。

文档中描述了自动凭据刷新的特定行为:

  

只有在使用时才会自动刷新凭据   默认客户端构造函数,它自己创建   InstanceProfileCredentialsProvider作为默认提供程序的一部分   链,或者当您传递InstanceProfileCredentialsProvider实例时   直接到客户端构造函数。如果你使用另一种方法   获取或传递实例配置文件凭据,您负责   检查并刷新过期的凭据。

通过直接传递AWSCredentials而不是AWSCredentialsProvider,您将负责检查和刷新过期的凭据。从好的方面来说,如果您想要明确地传递凭据,那么您的解决方法就可以了。

SimpleSQSClient有一个构造函数,可以更好地适用于您的用例:

new SimpleSQSClient(
    credentialProvider: com.amazonaws.auth.AWSCredentialsProvider,
    region: com.amazonaws.regions.Regions,
    buffered: Boolean
)

示例:

SimpleSQSClient sqs = SimpleSQSClient(new DefaultAWSCredentialsProviderChain(), Regions.US_EAST_1, false)

示例,明确使用InstanceProfileCredentialsProvider

SimpleSQSClient sqs = SimpleSQSClient(new InstanceProfileCredentialsProvider(), Regions.US_EAST_1, false)

进一步阅读: