创建IAM用户Access Key后调用S3 putObject提示密钥不存在
问题:新生成的IAM Access Key调用S3 putObject时提示密钥不存在
为拥有S3对象写入权限的IAM用户创建Access Key后,立即用该密钥调用S3的putObject方法上传对象,执行时出现错误:
the aws access key id you provided does not exist in our records
代码明确使用刚生成的凭据,但认证失败。相关代码如下:
import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.iam.IamClient; import software.amazon.awssdk.services.iam.model.CreateAccessKeyRequest; import software.amazon.awssdk.services.iam.model.CreateAccessKeyResponse; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.model.PutObjectRequest; public static String[] creds() { IamClient fiddler = IamClient.builder().region(Region.AWS_GLOBAL). credentialsProvider( StaticCredentialsProvider.create( AwsBasicCredentials.create( "Access Key", "Secret Key"))) .build(); CreateAccessKeyResponse cakr = fiddler.createAccessKey( CreateAccessKeyRequest.builder(). userName("user").build()); return new String[] {cakr.accessKey().accessKeyId(), cakr.accessKey().secretAccessKey()}; } String[] cakr = creds(); S3Client iamUser = S3Client.builder().region(Region.AWS_GLOBAL). credentialsProvider( StaticCredentialsProvider.create( AwsBasicCredentials.builder(). accessKeyId(cakr[0]). secretAccessKey(cakr[1]).build())) .build(); File keyFile = new File(System.getProperty( "java.io.tmpdir"), "why" + ".key"); try (FileOutputStream writer = new FileOutputStream( keyFile)) { writer.write("why".getBytes()); } catch (IOException ex) { ex.printStackTrace(); } iamUser.putObject(PutObjectRequest.builder() .bucket("bucket"). key("pkeys/" + "why" + ".key").build(), keyFile.toPath());
核心原因
AWS IAM Access Key创建后存在全局同步延迟,刚生成的密钥不会立即在所有AWS服务端点生效,尤其是S3这类跨区域服务,同步耗时从几秒到几分钟不等。代码在生成密钥后立刻调用S3接口,此时密钥还未同步到S3的认证系统,因此触发密钥不存在的错误。
解决方案
1. 添加同步等待逻辑
在生成Access Key后,增加一段等待时间,确保密钥完成全局同步:
String[] cakr = creds(); // 等待30秒,可根据实际情况调整时长 Thread.sleep(30000);
2. 修正S3客户端的区域配置
S3服务不支持Region.AWS_GLOBAL,必须指定与目标桶一致的具体区域(比如Region.US_EAST_1),错误的区域配置会加剧同步延迟或导致认证失败:
S3Client iamUser = S3Client.builder() .region(Region.US_EAST_1) // 替换为你的S3桶所在区域 .credentialsProvider( StaticCredentialsProvider.create( AwsBasicCredentials.builder() .accessKeyId(cakr[0]) .secretAccessKey(cakr[1]) .build())) .build();
3. 可选:验证密钥激活状态
如果等待后仍失败,可先调用IAM接口验证密钥是否已激活,确认后再调用S3:
// 等待后添加验证逻辑 IamClient verifyClient = IamClient.builder() .region(Region.AWS_GLOBAL) .credentialsProvider(StaticCredentialsProvider.create( AwsBasicCredentials.create("你的管理Access Key", "你的管理Secret Key"))) .build(); // 调用该接口确认密钥已存在并可被查询 verifyClient.getAccessKeyLastUsed(GetAccessKeyLastUsedRequest.builder() .accessKeyId(cakr[0]) .build());
额外检查项
- 确认用于创建Access Key的父凭据拥有
iam:CreateAccessKey权限,且目标IAM用户存在。 - 检查S3桶的权限策略,确保目标IAM用户拥有
s3:PutObject权限,且桶策略未拒绝该用户的请求。
内容的提问来源于stack exchange,提问作者Zan X
相关产品推荐
相关产品推荐

