S3AsyncClient.getObject为何需要s3:ListBucket权限?
为什么调用S3AsyncClient.getObject会要求s3:ListBucket权限?
我原本以为以下代码仅需s3:GetObject权限即可执行S3AsyncClient.getObject操作:
import software.amazon.awssdk.core.async.AsyncResponseTransformer; import software.amazon.awssdk.services.s3.S3AsyncClient; import software.amazon.awssdk.services.s3.model.GetObjectRequest; private final S3AsyncClient s3; @GetMapping(path = "/{file}") Mono<ResponseEntity<Flux<ByteBuffer>>> downloadFile(@PathVariable("file") String file) { final var request = GetObjectRequest.builder() .bucket("my-bucket") .key("aPrefix/" + file) .build(); return Mono.fromFuture(s3.getObject(request, AsyncResponseTransformer.toPublisher())) .map( response -> ResponseEntity.ok() .header(CONTENT_TYPE, response.response().contentType()) .header( CONTENT_LENGTH, Long.toString(response.response().contentLength())) .header(CACHE_CONTROL, CACHE_CONTROL_VALUE) .body(Flux.from(response))); }
但运行时却出现错误:
... is not authorized to perform: s3:ListBucket on resource: ...
原因分析
- 对象不存在时的权限校验逻辑:AWS S3的权限体系中,当请求的对象不存在时,SDK会隐式执行
ListBucket操作来确认对象状态——这是为了区分“对象不存在”和“无权限访问对象”两种场景。如果IAM角色没有ListBucket权限,这个前置校验就会直接失败,抛出权限不足的错误。 - SDK的内部行为:AWS Java异步客户端在处理
getObject请求时,会做一些前置检查,比如验证目标key是否存在于bucket中,这个过程会触发ListBucket调用。哪怕你明确指定了key,只要对象实际不存在,就会触发这个检查。 - 权限资源范围不匹配:
s3:ListBucket权限的作用对象是bucket本身(例如arn:aws:s3:::my-bucket),而s3:GetObject权限的作用对象是bucket下的具体对象(例如arn:aws:s3:::my-bucket/aPrefix/*)。如果你的IAM策略只给了对象路径的GetObject权限,没有给bucket的ListBucket权限,就会出现这个错误。
解决方案
- 补充IAM权限:在策略中添加针对目标bucket的
s3:ListBucket权限,同时保留对象路径的s3:GetObject权限; - 确认对象存在:如果能保证请求的对象一定存在,这个隐式检查不会触发,但实际场景中建议还是补充权限以避免异常;
- 调整客户端配置:部分场景下可以通过客户端配置关闭这个隐式检查,但不推荐,因为会丢失错误场景的区分能力。
内容的提问来源于stack exchange,提问作者user482745
相关产品推荐
相关产品推荐

