AWS S3 Java SDK调用报403 AccessDenied权限异常
问题成因
这是S3权限配置最常见的新手坑,核心是对桶策略Principal的逻辑理解错误,加上SDK凭证匹配问题共同导致的:
- 你配置的
"AWS": "arn:aws:iam::9123...123:root"根本不是给账号下所有IAM身份开放权限,这个配置的实际含义是仅信任该账号下的身份,不会自动为账号内的IAM用户、角色、临时凭证授予S3访问权限。同账号下的IAM身份要访问S3,要么自身附加的IAM权限策略允许对应S3操作,要么桶策略里直接指定该身份的ARN为授权主体,缺一个环节都会返回403。 - 你的Java代码没有显式指定访问凭证,默认走AWS SDK的默认凭证链查找凭证(查找顺序为系统环境变量、JVM系统属性、本地
~/.aws/credentials配置文件、云主机实例角色等),如果当前加载到的凭证不属于9123...123这个账号,会直接因为主体不匹配被拒绝。 - 把
Principal改成"*"能正常访问,是因为这个配置直接放开了身份校验,允许任意匿名/认证身份访问对应资源,完全跳过了主体匹配逻辑,但这个配置属于公网公开访问,生产环境用有极大的数据泄露、流量盗刷风险。
修复方案
按优先级从高到低选择对应方案即可:
- 先排查凭证匹配问题:在代码里加入STS调用打印当前实际使用的调用身份,确认账号ID、身份ARN和预期一致,先排除凭证配错(比如本地配置了其他账号的AK/SK、环境变量里的凭证不对)的基础问题,示例代码:
final AmazonS3 s3 = AmazonS3ClientBuilder.standard().withRegion("us-east-1").build(); // 新增以下代码打印当前调用身份 AWSSecurityTokenService sts = AWSSecurityTokenServiceClientBuilder.standard().withRegion("us-east-1").build(); System.out.println("当前调用身份:" + sts.getCallerIdentity());
- 方案1(同账号访问首选):给SDK当前使用的IAM身份(IAM用户/应用运行的EC2/ECS/Lambda实例角色等)附加S3访问权限,权限策略示例如下,附加后不需要修改现有桶策略即可正常访问:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::go_bucket/*" } ] }
- 方案2(跨账号访问/不想修改IAM权限时使用):直接修改桶策略的
Principal字段,填入你实际使用的IAM身份的完整ARN(比如arn:aws:iam::9123...123:user/your-java-app-user),这种方式不需要给身份额外附加IAM权限即可访问。 - 仅本地临时测试时可以暂时保留
Principal: "*"的配置,但测试完成后必须立即改回,生产环境禁止长期使用这个配置,避免出现数据安全事故。
内容的提问来源于stack exchange,提问作者CR Sardar
相关产品推荐
相关产品推荐

