使用PHP SDK可访问单个AWS S3对象,列取对象时遭403拒绝
问题:AWS S3可生成单个对象预签名URL,但无法列取对象列表返回403错误
我拥有某AWS S3存储桶的访问权限,可通过以下PHP代码拉取单个文件并生成预签名URL:
public function show_s3_object($file_key) { $s3_bucket = getenv('S3_BUCKET'); $s3_key = getenv('S3_KEY'); $s3_secret = getenv('S3_SECRET'); if(!empty($file_key)) { $credentials = new Credentials($s3_key, $s3_secret); $bucket = $s3_bucket; $s3Client = new S3Client([ 'version' => 'latest', 'region' => 'us-east-1', 'credentials' => $credentials ]); $cmd = $s3Client->getCommand('GetObject', [ 'Bucket' => $bucket, 'Key' => $file_key ]); $request = $s3Client->createPresignedRequest($cmd, '+10 minutes'); $signedUrl = (string) $request->getUri(); return $signedUrl; } }
但尝试列取该存储桶内的对象时,始终返回403 Forbidden错误。我已尝试多种列取方式,例如:
$cmd = $s3Client->getCommand('ListObjects', [ 'Bucket' => $bucket ]);
或
$cmd = $s3client->listObjects([ 'Bucket' => $bucket ]);
当前使用以下代码仍触发403错误:
public function list_objects() { //correct code semmingly but getting 403 forbidden $s3_bucket = getenv('S3_BUCKET'); $s3_key = getenv('S3_KEY'); $s3_secret = getenv('S3_SECRET'); $credentials = new Credentials($s3_key, $s3_secret); $s3Client = new S3Client([ 'version' => 'latest', 'region' => 'us-east-1', 'credentials' => $credentials ]); try { $objects = $s3Client->getIterator('ListObjects', array( 'Bucket' => $s3_bucket )); echo "Keys retrieved!\n"; foreach ($objects as $object) { echo $object['Key'] . "\n"; } } catch (S3Exception $e) { echo $e->getMessage() . "\n"; } }
原因与解决方案
核心原因是你使用的IAM凭证仅拥有单个对象的访问权限(s3:GetObject),但缺少存储桶级别的列取对象权限(s3:ListBucket)。
具体分析:
- 生成预签名URL或直接获取单个对象,只需要目标对象的
s3:GetObject权限,该权限可通过IAM策略授予单个对象路径,示例:{ "Effect": "Allow", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::your-bucket-name/*" } - 而列取存储桶内对象(
ListObjects/listObjects/getIterator('ListObjects'))需要存储桶级别的s3:ListBucket权限,对应的IAM策略需指定存储桶本身作为资源:{ "Effect": "Allow", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::your-bucket-name" }
解决步骤:
- 登录AWS控制台,进入IAM服务,找到当前凭证对应的IAM用户或角色。
- 编辑该实体的权限策略,添加包含
s3:ListBucket权限的语句,注意资源要指向存储桶ARN(不带/*后缀)。 - 保存策略后重新测试列取对象代码,403错误即可解决。
权限缩小优化(可选):
如果仅需列取特定前缀下的对象,可在s3:ListBucket策略中添加条件限制,进一步缩小权限范围:
{ "Effect": "Allow", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::your-bucket-name", "Condition": { "StringLike": { "s3:prefix": "your-target-prefix/*" } } }
内容的提问来源于stack exchange,提问作者Dylano236
相关产品推荐
相关产品推荐

