订阅SNS主题时触发SNSException:请求中安全令牌无效
问题背景
我尝试使用IAM用户的AWS访问凭证,让EC2服务器上的Java应用订阅SNS主题。已给该IAM用户附加AmazonSNSFullAccess权限策略,同时修改了主题的访问策略,具体内容如下:
{ "Version": "2008-10-17", "Id": "__default_policy_ID", "Statement": [ { "Sid": "__default_statement_ID", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::<account_number>:user/<IAMuserName>" }, "Action": [ "SNS:GetTopicAttributes", "SNS:SetTopicAttributes", "SNS:AddPermission", "SNS:RemovePermission", "SNS:DeleteTopic", "SNS:Subscribe", "SNS:ListSubscriptionsByTopic", "SNS:Publish" ], "Resource": "arn:aws:sns:us-east-1:<Accountnumber>:<topic>" } ] }
但完成配置后,无论是本地电脑还是同一AWS账号下的EC2服务器运行应用,都会触发以下403错误:
software.amazon.awssdk.services.sns.model.SnsException: The security token included in the request is invalid. (Service: Sns, Status Code: 403, Request ID:
订阅核心代码:
SubscribeResponse response = snsClient.subscribe(getSubscribeRequest(instanceCommunicationTopicARN, "https", "/api/notification/ec2-communications")); private SubscribeRequest getSubscribeRequest(String topicARN, String protocol, String endpoint) { return SubscribeRequest.builder() .topicArn(topicARN) .protocol(protocol) .endpoint(endpoint) .build(); }
SNSClient配置类:
@Configuration public class AmazonSNSConfig { @Value("${spring.application.name}") public String awsAccessKey; @Value("${jsa.aws.secret_access_key}") public String awsSecretKey; @Value("${jsa.s3.region}") public String awsRegion; @Bean public SnsClient initializeAmazonSnsClient() { return SnsClient.builder() .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create( awsAccessKey, awsSecretKey))) .region(Region.of(awsRegion)) .build(); } }
补充:该IAM用户未启用MFA,且是创建访问密钥和秘密密钥后才附加的AmazonSNSFullAccess策略,怀疑是否由此导致问题。
解决步骤
先查凭证正确性
确认代码加载的awsAccessKey和awsSecretKey与IAM用户生成的密钥完全一致,不要有空格、换行或复制错误。可以用AWS CLI直接测试:aws sns subscribe --topic-arn arn:aws:sns:us-east-1:<Accountnumber>:<topic> --protocol https --endpoint "/api/notification/ec2-communications" --region us-east-1 --profile <你的IAM用户配置文件>如果CLI报错,说明凭证本身有问题;如果CLI成功,那就是代码里的凭证加载逻辑出错。
权限策略生效验证
创建密钥后再附加策略不会影响生效——IAM权限是实时生效的,无需重新生成密钥。但可以做以下检查:- 登录AWS控制台,进入IAM用户页面,查看「权限」标签,确认
AmazonSNSFullAccess已正确附加,且没有**拒绝策略(Deny)**覆盖允许权限。 - 用IAM的「模拟策略」功能,测试该用户执行
sns:Subscribe操作是否被允许,目标资源填你的SNS主题ARN。
- 登录AWS控制台,进入IAM用户页面,查看「权限」标签,确认
简化主题访问策略
同一账号下的IAM用户只要有IAM权限就可以访问SNS主题,不需要额外配置主题访问策略——主题策略主要用于跨账号或服务授权。建议暂时移除自定义的主题策略,测试是否能正常订阅。如果一定要保留,务必确保Principal里的ARN(账号ID、用户名)是实际正确的值,不要留占位符。修复代码配置错误
你的SNSClient配置类有明显问题:@Value("${spring.application.name}")绑定的是awsAccessKey?这完全错误!spring.application.name是应用名称,不是AWS访问密钥,应该改成对应的配置项,比如@Value("${jsa.aws.access_key}"),确保配置文件的key和代码中的@Value参数一致。- 检查
awsRegion是否与SNS主题所在区域(us-east-1)一致,区域不匹配也会导致请求失败。 - 确认配置文件(如
application.properties)中jsa.aws.secret_access_key、jsa.s3.region(建议改名为jsa.sns.region避免混淆)的值正确。
其他排查方向
检查是否有AWS组织的SCP(服务控制策略)限制了该账号的SNS操作;如果EC2通过VPC端点访问SNS,还要确认VPC端点的策略是否允许该IAM用户的操作。
内容的提问来源于stack exchange,提问作者Maurice

