Как отображать защищенные изображения Amazon S3 на моем защищенном сайте с помощью PHP?

Я пытаюсь переместить изображения для своего сайта с моего хоста на облачный хостинг 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𭼗, чтобы настроить это, но затем не понимаю, какая безопасность мне нужна для моих объектов. Казалось, что если бы я сделал их приватными, они все равно не отображались бы, если бы я не использовал временную ссылку, как упоминалось ранее. Если бы я сделал их общедоступными, я мог бы перейти к ним напрямую, независимо от реферера.

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


person Bob    schedule 02.03.2011    source источник


Ответы (4)


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

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

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

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

person Geoff Appleford    schedule 03.03.2011
comment
У меня нет голосов на сегодня, но это правильно. Самостоятельная загрузка изображений на самом деле будет медленнее, чем просто разместить их самостоятельно, тем самым лишая преимущества внешнего хостинга на S3. - person Konerak; 03.03.2011
comment
Это имеет смысл, но кажется более сложной моделью безопасности через неизвестность. С тем же успехом я мог бы не использовать S3 и использовать файл .htaccess, чтобы отключить хотлинкинг, и использовать прокси-файл для отображения моего изображения, почти так, как предложил @mfonda, только локально. Итак, используя SDK, я не могу просто получить файл на основе значений аутентификации, которые я установил в config.inc.php? Думаю, я не очень понимаю, как получить файл как аутентифицированный пользователь. Есть ли какие-либо данные о политиках корзины, чтобы изображения были общедоступными, но доступными только для рефереров, которые я определяю? Это не сработало. - person Bob; 04.03.2011
comment
@Bob - это намного безопаснее. URL-адрес не может быть создан, если у человека нет вашего секретного ключа. Конечно, может быть проще серверировать файлы из локального хранилища, но тогда вы потеряете все преимущества S3 — емкость, ограниченную только вашей кредитной картой, огромную пропускную способность и масштабируемость и т. д. Вы можете создавать свои собственные политики доступа. См. docs.amazonwebservices.com/AmazonS3/latest/dev/, но это еще сложнее, и я не уверен, что это все равно сделает то, что вы хотите. - person Geoff Appleford; 04.03.2011
comment
Хорошо, преимущества использования S3 определенно огромны. Я сделал еще кое-что с политиками сегментов и нашел эту статью http://blog.cloudberrylab.com/2010/07/how-to-prevent-hotlinking-of-your.html Должно быть, я что-то неправильно настроил, так как теперь это работает. Изображения отображаются на моем сайте, конечно, невероятно быстро, и когда я нажимаю «Открыть изображение в новой вкладке», я получаю сообщение об отказе в доступе. Может ли этот реферер быть кем-то подделан? - person Bob; 04.03.2011
comment
@Bob - реферер - это просто заголовок http, поэтому его легко подделать. Есть даже расширения для Firefox, которые сделают это за вас. Использование политики корзины реферера отлично остановит обычного пользователя, но не остановит решительного и знающего пользователя. Но в любом случае хорошая ссылка. Я мог бы использовать политики сегментов для ресурсов, где абсолютная безопасность не является существенной. - person Geoff Appleford; 05.03.2011
comment
@Джефф, спасибо за ясность. Это то, что я понял, и после небольшого исследования действительно видел материал Firefox. Я думаю, что комбинация динамических URL-адресов и политики реферера ведра нам подойдет. Спасибо за ваш вклад. - person Bob; 07.03.2011

Вы можете использовать политики корзины в своей корзине 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/*"
          ]
        }
      }
    }
  ]
}
person Wes    schedule 20.09.2013

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

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

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

readfile('s3://my-bucket/my-images/php.gif');
person catalinux    schedule 20.01.2015

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