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

如何使用PHP在安全站点上显示受保护的AmazonS3图像?,php,image,amazon-s3,amazon-web-services,intranet,Php,Image,Amazon S3,Amazon Web Services,Intranet,我正在尝试将我的站点的图像从我的主机移动到AmazonS3云主机。这些图像是客户端工作站点的图像,无法公开。我希望它们最好使用亚马逊提供的PHPSDK显示在我的网站上 到目前为止,我已经能够为转换编写脚本,以便在数据库中查找记录、获取文件路径、适当命名并将其发送到Amazon //upload to s3 $s3->create_object($bucket, $folder.$file_name_new, array( 'fileUpload' => $file_t

我正在尝试将我的站点的图像从我的主机移动到AmazonS3云主机。这些图像是客户端工作站点的图像,无法公开。我希望它们最好使用亚马逊提供的PHPSDK显示在我的网站上

到目前为止,我已经能够为转换编写脚本,以便在数据库中查找记录、获取文件路径、适当命名并将其发送到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上传图像,我可以获取公共url,但我没有访问权限,或者我可以使用临时密钥获取公共url并显示图像

<?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 />


“alt='finding image'/>
使用此方法,我的缓存将如何工作?我猜每次我刷新页面或修改记录时,我都会再次拉取该图像,从而增加get请求

我还考虑过使用bucket策略只允许从某些引用者检索图像。我是否正确理解Amazon应该只从我指定的页面或域获取请求

我提到: 设置,但我不知道我的对象需要哪种安全性。似乎如果我将它们设置为私有,它们仍然不会显示,除非我像前面提到的那样使用临时链接。如果我把它们公之于众,我就可以直接导航到它们,而不管推荐人是谁


我是不是偏离了我要做的?S3真的不支持这一点,还是我缺少了一些简单的东西?我已经阅读了SDK文档和大量的搜索,我觉得这应该是一个更清晰的文档,所以希望这里的任何输入都可以在这种情况下帮助其他人。我读过一些人用一个唯一的ID命名这个文件,通过模糊来创建安全性,但在我的情况下,这并不能解决这个问题,对于任何试图确保安全的人来说,这可能不是最好的做法。

您可以从S3下载内容(在PHP脚本中),然后使用正确的标题提供给他们

作为一个粗略的例子,假设您在
image.php
中有以下内容:

$s3 = new AmazonS3();
$response = $s3->get_object($bucket, $image_name);
if (!$response->isOK()) {
    throw new Exception('Error downloading file from S3');
}
header("Content-Type: image/jpeg");
header("Content-Length: " . strlen($response->body));
die($response->body);
然后在HTML代码中,您可以

<img src="image.php">

为图像提供服务的最佳方法是使用PHP SDK生成url。这样,下载就可以直接从S3下载给用户

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

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


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

您可以在Amazon bucket中使用bucket策略来允许应用程序的域访问该文件。事实上,您甚至可以将您的本地开发域(例如:mylocaldomain.local)添加到访问列表中,这样您就可以获得图像。Amazon在此处提供了示例bucket策略:。这对我提供图像服务非常有帮助

下面的策略解决了让我想到这个话题的问题:

    {
       "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/*"
          ]
        }
      }
    }
  ]
}

当您谈到安全性和保护数据不受未经授权的用户攻击时,有一点是明确的:您必须在每次访问您有权访问的资源时进行检查

这意味着,生成任何人都可以访问的url(可能很难获得,但仍然…)。唯一的解决方案是使用图像代理。您可以使用php脚本来实现这一点

亚马逊博客上有一篇很好的文章建议使用readfile


我今天的票数没有了,但这是正确的。首先自己下载图片实际上比自己托管要慢,从而丢掉了S3上外部托管的优势。这很有道理,但似乎是一个更复杂的隐蔽安全模型。我也可以不使用S3,而使用.htaccess文件来禁用热链接,并使用代理文件来显示我的图像,就像@mfonda建议的那样,只在本地显示。所以,使用SDK,我不能仅仅根据我在config.inc.php中设置的身份验证值获取文件?我想我并不真正理解如何作为经过身份验证的用户获取文件。是否有关于bucket策略的任何输入,以便图像是公共的,但仅对我定义的引用者可用?这似乎不起作用。@Bob-比这安全多了。除非此人拥有您的密钥,否则无法创建url。当然,从本地存储为文件提供服务器可能更简单,但这样一来,您就失去了S3的所有好处—容量仅受您的信用卡、巨大的带宽和可扩展性等的限制。您可以创建自己的访问策略。看,但这更复杂,我不确定它是否能满足你的要求。好的,使用S3的好处肯定是巨大的。我在bucket策略方面做了更多的工作,发现这篇文章我一定是配置了一些错误的东西,因为它现在似乎可以工作了。当然,图片显示在我的网站上,速度非常快,当我点击“在新选项卡中打开图片”时,我会收到拒绝访问的消息。那么,那个推荐人会被别人欺骗吗?@Bob-推荐人只是一个http头,所以很容易被欺骗。甚至有Firefox扩展可以为您实现这一点。使用推荐人桶策略将非常适合f
readfile('s3://my-bucket/my-images/php.gif');