2023年10月如何用AWS Java SDK 1.12.x开启S3 Bucket公共读取权限?
如何通过Java代码实现S3桶公共读取权限(AWS 2023年4月规则变更后)
2023年4月AWS S3规则更新后,ACL方式的公共权限不再生效,必须先禁用桶的Public Access Block,再配置公共读取桶策略。目前手动在控制台关闭“阻止所有公共访问”后,网页可以正常读取index.html,但需要动态创建桶,无法逐个手动操作。代码中设置桶策略成功,但调用setPublicAccessBlock时提示Access Denied,求解决方法。
用户提供的代码如下:
public S3_UpdaterController() { s3client.createBucket("ecotest123456789"); List buckets = s3client.listBuckets(); for (Object object : buckets) { System.out.println(object.toString()); } String bucketname = "ecotest123456789"; String initialString = "<html>test</html>"; java.io.InputStream targetStream = new java.io.ByteArrayInputStream(initialString.getBytes()); PutObjectRequest putObjectRequest = new PutObjectRequest("ecotest123456789", "index.html", targetStream,null); //s3client.deleteBucketPolicy(bucketname); s3client.setBucketPolicy(bucketname, getPublicReadPolicy(bucketname)); BucketPolicy bucket_policy = s3client.getBucketPolicy(bucketname); System.out.println(bucket_policy.getPolicyText()); AccessControlList acl = new AccessControlList(); acl.grantPermission(GroupGrantee.AllUsers, Permission.Read); //all users or authenticated //putObjectRequest.setAccessControlList(acl); s3client.putObject(putObjectRequest);//.withCannedAcl(CannedAccessControlList.PublicRead)); s3client.setBucketWebsiteConfiguration(bucketname,new BucketWebsiteConfiguration("index.html")); //THIS ONE FAILS WITH ACCESS DENIED s3client.setPublicAccessBlock(new SetPublicAccessBlockRequest().withBucketName(bucketname)); } public static String getPublicReadPolicy(String bucket_name) { Policy bucket_policy = new Policy().withStatements( new Statement(Statement.Effect.Allow) .withPrincipals(Principal.AllUsers) .withActions(S3Actions.GetObject) .withResources(new Resource( "arn:aws:s3:::" + bucket_name + "/*"))); return bucket_policy.toJson(); }
解决步骤
1. 确保IAM权限足够
调用setPublicAccessBlock需要IAM实体(用户/角色)拥有s3:PutPublicAccessBlock权限,同时检查是否存在组织级S3公共访问阻止策略限制——如果组织强制开启了公共访问阻止,即使IAM有权限也无法修改,需要联系管理员调整组织策略。
2. 修正setPublicAccessBlock的代码参数
当前代码仅指定了桶名,没有设置具体的公共访问阻止配置,默认不会关闭所有限制。需要明确设置四个参数为false,以完全禁用Public Access Block:
// 替换原有的setPublicAccessBlock调用 PublicAccessBlockConfiguration config = new PublicAccessBlockConfiguration() .withBlockPublicAcls(false) .withIgnorePublicAcls(false) .withBlockPublicPolicy(false) .withRestrictPublicBuckets(false); SetPublicAccessBlockRequest request = new SetPublicAccessBlockRequest() .withBucketName(bucketname) .withPublicAccessBlockConfiguration(config); s3client.setPublicAccessBlock(request);
3. 调整操作顺序
正确的流程应该是:创建桶 → 禁用Public Access Block → 设置桶策略 → 上传对象 → 配置网站。因为如果Public Access Block开启,后续的桶策略可能无法生效。调整后的代码顺序参考:
public S3_UpdaterController() { String bucketname = "ecotest123456789"; // 1. 创建桶 s3client.createBucket(bucketname); // 2. 禁用Public Access Block(修正后的代码) PublicAccessBlockConfiguration config = new PublicAccessBlockConfiguration() .withBlockPublicAcls(false) .withIgnorePublicAcls(false) .withBlockPublicPolicy(false) .withRestrictPublicBuckets(false); SetPublicAccessBlockRequest request = new SetPublicAccessBlockRequest() .withBucketName(bucketname) .withPublicAccessBlockConfiguration(config); s3client.setPublicAccessBlock(request); // 3. 设置公共读取桶策略 s3client.setBucketPolicy(bucketname, getPublicReadPolicy(bucketname)); // 4. 上传对象(可选:设置对象的公共读取权限,配合桶策略) String initialString = "<html>test</html>"; java.io.InputStream targetStream = new java.io.ByteArrayInputStream(initialString.getBytes()); PutObjectRequest putObjectRequest = new PutObjectRequest(bucketname, "index.html", targetStream,null) .withCannedAcl(CannedAccessControlList.PublicRead); // 可选,增强兼容性 s3client.putObject(putObjectRequest); // 5. 配置静态网站 s3client.setBucketWebsiteConfiguration(bucketname,new BucketWebsiteConfiguration("index.html")); // 验证桶列表 List buckets = s3client.listBuckets(); for (Object object : buckets) { System.out.println(object.toString()); } }
4. 验证桶策略和访问权限
设置完成后,可通过AWS控制台检查桶的Public Access Block状态是否为“关闭所有公共访问阻止”,同时确认桶策略已正确应用。访问网站端点验证index.html是否可正常访问。
内容的提问来源于stack exchange,提问作者wellumies
相关产品推荐
相关产品推荐

