Как отобразить защищенные изображения Amazon S3 на моем защищенном сайте с помощью PHP? - PullRequest
25 голосов
/ 02 марта 2011

Я пытаюсь переместить изображения для своего сайта с моего хостинга на облачный хостинг Amazon S3. Эти изображения с рабочих мест клиентов и не могут быть общедоступными. Я хотел бы, чтобы они отображались на моем сайте, предпочтительно с помощью PHP SDK, доступного на Amazon.

До сих пор я был в состоянии написать сценарий для преобразования, так что я просматриваю записи в моей базе данных, выбираю путь к файлу, присваиваю ему соответствующее имя и отправляю его в 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 />

Используя этот метод, как будет работать мое кэширование? Я предполагаю, что каждый раз, когда я обновляю страницу или изменяю одну из своих записей, я буду снова вытягивать это изображение, увеличивая количество запросов на получение.

Я также рассмотрел использование политик сегмента, чтобы разрешить получение изображений только от определенных источников. Правильно ли я понимаю, что Amazon должен получать запросы только с указанных мной страниц или доменов?

Я ссылался: https://forums.aws.amazon.com/thread.jspa?messageID=188183&#188183, чтобы установить это, но затем я не понимаю, какая безопасность мне нужна для моих объектов. Казалось, что если бы я сделал их Private, они все равно не отображались бы, если бы я не использовал временную ссылку, как упоминалось ранее. Если бы я сделал их общедоступными, я мог бы перейти к ним напрямую, независимо от реферера.

Я далеко от того, что я пытаюсь сделать здесь? Это на самом деле не поддерживается S3, или я упускаю что-то простое? Я просмотрел документацию по SDK и много разыскивал, и чувствую, что это должно быть немного более четко задокументировано, так что, надеюсь, любой вклад здесь может помочь другим в этой ситуации. Я читал тех, кто называет файл уникальным идентификатором, создавая безопасность через неизвестность, но это не повлияет на мою ситуацию, и, вероятно, не лучшую практику для тех, кто пытается быть в безопасности.

Ответы [ 4 ]

24 голосов
/ 03 марта 2011

Лучший способ показать ваши изображения - это создать URL с помощью PHP SDK.Таким образом, загрузка идет прямо с S3 для ваших пользователей.

Вам не нужно скачивать через свои серверы, как предложила @mfonda - вы можете установить любые заголовки кэширования, которые вам нравятся, на объектах S3 - и в этом случае вы потеряете некоторые основные преимущества использования S3.

Однако, как вы указали в своем вопросе, URL-адрес всегда будет изменяться (фактически строка запроса), поэтому браузеры не будут кэшировать файл.Простой обходной путь - просто всегда использовать одну и ту же дату окончания срока действия, чтобы всегда генерировалась одна и та же строка запроса.Или лучше все же «кешировать» URL-адрес самостоятельно (например, в базе данных) и использовать его каждый раз.

Вы, очевидно, должны будете установить время истечения где-то в далеком будущем, но вы можете регенерировать эти URL-адреса так часто, как пожелаете.Например, в вашей базе данных вы должны хранить сгенерированный URL-адрес и дату истечения срока действия (вы можете также проанализировать это из URL-адреса).Затем либо вы просто используете существующий URL-адрес, либо, если срок действия истек, создайте новый.и т.д ...

8 голосов
/ 20 сентября 2013

Вы можете использовать политики корзины в своей корзине Amazon, чтобы позволить домену вашего приложения получить доступ к файлу.На самом деле, вы даже можете добавить свой локальный домен разработчика (например, mylocaldomain.local) в список доступа, и вы сможете получить свои изображения.Amazon предоставляет примеры политик ведра здесь: 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/*"
          ]
        }
      }
    }
  ]
}
2 голосов
/ 21 января 2015

Когда вы говорите о безопасности и защите данных от неавторизованных пользователей, что-то ясно: вам нужно проверять каждый раз, когда вы получаете доступ к тому ресурсу, на который у вас есть права.

Это означает, что генерация URL можетбыть доступным для любого (может быть трудно получить, но все же ...).Единственное решение - это прокси изображений.Вы можете сделать это с помощью PHP-скрипта.

Есть хорошая статья из блога Amazon, которая предлагает использовать readfile, http://blogs.aws.amazon.com/php/post/Tx2C4WJBMSMW68A/Streaming-Amazon-S3-Objects-From-a-Web-Server

readfile('s3://my-bucket/my-images/php.gif');
0 голосов
/ 03 марта 2011

Вы можете загрузить содержимое из 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">
...