如何使用 PHP 在我的安全站点上显示受保护的 Amazon S3 图像?

我正在尝试将我的站点的图像从我的主机移动到 Amazon S3 云托管。这些图像是客户端工作站点的,不能公开提供。我希望它们最好显示在我的网站上,最好使用亚马逊提供的PHP SDK。

到目前为止,我已经能够编写转换脚本,以便我在数据库中查找记录,获取文件路径,适当地命名,然后将其发送到Amazon。

    //upload to s3
$s3->create_object($bucket, $folder.$file_name_new, array(
    'fileUpload' => $file_temp,
    'acl' => AmazonS3::ACL_PRIVATE, //access denied, grantee only own
    //'acl' => AmazonS3::ACL_PUBLIC, //image displayed
    //'acl' => AmazonS3::ACL_OPEN, //image displayed, grantee everyone has open permission
    //'acl' => AmazonS3::ACL_AUTH_READ, //image not displayed, grantee auth users has open permissions
    //'acl' => AmazonS3::ACL_OWNER_READ, //image not displayed, grantee only ryan
    //'acl' => AmazonS3::ACL_OWNER_FULL_CONTROL, //image not displayed, grantee only ryan
    'storage' => AmazonS3::STORAGE_REDUCED
    )
    );

在我复制所有内容之前,我创建了一个简单的表单来测试上传和显示图像。如果我使用ACL_PRIVATE上传图像,我可以获取公共网址,但我将无法访问,或者我可以使用临时密钥获取公共网址并可以显示图像。

<?php
//display the image link
$temp_link = $s3->get_object_url($bucket, $folder.$file_name_new, '1 minute');
?>
<a href='<?php echo $temp_link; ?>'><?php echo $temp_link; ?></a><br />
<img src='<?php echo $temp_link; ?>' alt='finding image' /><br />

使用此方法,我的缓存将如何工作?我猜每次刷新页面或修改我的一条记录时,我都会再次拉动该图像,从而增加我的get请求。

我还考虑使用存储桶策略,仅允许从某些引荐来源网址检索图像。我是否正确地理解,亚马逊应该只从我指定的页面或域中提取请求?

我引用了:https://forums.aws.amazon.com/thread.jspa?messageID=188183&#188183 设置它,但是后来我对对象需要哪种安全性感到困惑。似乎如果我将它们设置为私有,它们仍然不会显示,除非我像前面提到的那样使用临时链接。如果我公开了它们,我可以直接导航到它们,而不管引荐来源人是谁。

我是否偏离了我在这里想要做的事情?S3 是否真的支持这一点,或者我错过了一些简单的东西?我已经浏览了SDK文档和大量搜索,并觉得这应该更清楚地记录下来,所以希望这里的任何输入都能在这种情况下帮助其他人。我读过其他人用唯一的ID命名文件,通过晦涩难懂来创建安全性,但这在我的情况下不会削减它,并且对于任何试图安全的人来说可能不是最佳实践。


答案 1

提供图像的最佳方式是使用 PHP SDK 生成 url。这样,下载直接从 S3 传输到您的用户。

您无需按照@mfonda建议通过服务器下载 - 您可以在S3对象上设置您喜欢的任何缓存标头 - 如果您这样做,您将失去使用S3的一些主要好处。

但是,正如您在问题中指出的那样,url将始终更改(实际上是查询字符串),因此浏览器不会缓存文件。简单的解决方法是始终使用相同的到期日期,以便始终生成相同的查询字符串。或者最好是自己“缓存”url(例如在数据库中)并每次都重用它。

显然,您必须将到期时间设置在遥远的将来,但是如果您愿意,可以每隔一段时间重新生成这些URL。例如,在您的数据库中,您将存储生成的URL和到期日期(您也可以从url解析它)。然后,您要么只使用现有的URL,要么如果到期日期已过,则生成一个新URL。等。。。


答案 2

您可以使用 Amazon 存储桶中的存储桶策略来允许应用程序的域访问该文件。实际上,您甚至可以将本地开发域(例如:mylocaldomain.local)添加到访问列表中,您将能够获取映像。亚马逊在此处提供了示例存储桶策略:http://docs.aws.amazon.com/AmazonS3/latest/dev/AccessPolicyLanguage_UseCases_s3_a.html。这对帮助我提供图像非常有帮助。

下面的政策解决了将我带到SO主题的问题:

    {
       "Version":"2008-10-17",
       "Id":"http referer policy example",
       "Statement":[
    {
      "Sid":"Allow get requests originated from www.example.com and example.com",
      "Effect":"Allow",
      "Principal":"*",
      "Action":"s3:GetObject",
      "Resource":"arn:aws:s3:::examplebucket/*",
      "Condition":{
        "StringLike":{
          "aws:Referer":[
            "http://www.example.com/*",
            "http://example.com/*"
          ]
        }
      }
    }
  ]
}

推荐