如何测试 S3 对象是否不存在 AWS PHP SDK(版本 3)?

How to test if S3 object does not exist AWS PHP SDK (Version 3)?

我已经为 AWS SDK in PHP to send the keys for files on an S3 bucket and retrieve a pre-signed url, which more or less follows this example 写了一个集成。这非常有效,除了我现在需要检查文件是否存在于 s3 上,如果不存在则 return 空字符串。

我正在使用以下代码执行此操作:

<?php

public function getUrl($key, $region, $version, $fileBucket): string
{
    $this->s3Client = new Aws\S3\S3Client([
        'region' => $region,
        'version' => $version,
    ]);

    if ($this->s3Client->doesObjectExist($fileBucket, $key) === false) {
       return '';
    }

    $cmd = $this->s3Client->getCommand('GetObject', [
        'Bucket' => $fileBucket,
        'Key' => $key
    ]);

    $request = $this->s3Client->createPresignedRequest($cmd, $preSignedExpiration);

    $preSignedUrl = (string) $request->getUri();

    return $preSignedUrl ?? '';
}

我的代码 return 完美地编辑了预签名的 url,直到我添加了检查方法 doesObjectExist() 的 if 语句。 doesObjectExist() returns false 对于我在 S3 上的所有对象,而不仅仅是那些具有 S3 存储桶中不存在的 $key 的对象。这样就排除了 S3 密钥、存储桶或 api 密钥无效的可能性,这是 answer I have come across 主要研究此问题的。

此外,如果您碰巧知道使用 $cmd 或 $request 中 returned 的内容来执行此操作,而无需调用 doesObjectExist()(如果可能的话),这将简化我的操作码一下。

编辑:

我访问 AWS S3 API 的 IAM 用户的策略如下所示:

{    
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:ListBucket",
                "s3:DeleteObject"
            ],
            "Resource": [
                "arn:aws:s3:::example-dev-us-east-1-111111111111",
                "arn:aws:s3:::example-dev-us-east-1-111111111111/*"
            ]
        }
    ]
}

s3 存储桶策略如下所示:

       {
        "Sid": "dev-web-app-get-policy",
        "Effect": "Allow",
        "Principal": {
            "AWS": "arn:aws:iam::2222222222:role/example-dev-us-east-1-111111111111"
        },
        "Action": [
            "s3:GetObject",
            "s3:DeleteObject",
            "s3:ListBucket"
        ],
        "Resource": [
            "arn:aws:s3:::example-dev-us-east-1-111111111111",
            "arn:aws:s3:::example-dev-us-east-1-111111111111/*"
        ]
    }

所以看来我应该能够访问所需的资源。为了安全起见,我列出了假的桶名。但是我已经检查了控制台中的那些 mathc s3。

当尝试像这样调用 HeadObject 的 api 时:

$this->s3Client->headObject([
    'Bucket' => $fileBucket,
    'Key' => $key
]);

我收到以下消息:

"Error executing \"HeadObject\" on \"https://example-dev-us-east-1-111111111111/54bf7350-a819-41dd-9da3-3710eb8b095a-Screenshot_2021-03-09_20-15-12.png\"; AWS HTTP error: Client error: `HEAD https://example-dev-us-east-1-111111111111/54bf7350-a819-41dd-9da3-3710eb8b095a-Screenshot_2021-03-09_20-15-12.png` resulted in a `403 Forbidden` response  (client): 403 Forbidden (Request-ID: XR6W77BB817407K2) - ",
"url": "/files.json"

不确定是否有帮助。

谢谢!

您需要 s3:GetObject 权限才能调用 HeadObject API,这是 PHP SDK 在您的代码调用 doesObjectExist() 时调用的权限。

If the object you request does not exist, the error Amazon S3 returns depends on whether you also have the s3:ListBucket permission.

  • If you have the s3:ListBucket permission on the bucket, Amazon S3 returns an HTTP status code 404 ("no such key") error.
  • If you don’t have the s3:ListBucket permission, Amazon S3 returns an HTTP status code 403 ("access denied") error.

因此,您可能有 s3:ListBucket 但没有 s3:GetObject。