Как отображать защищенные изображения Amazon S3 на моем защищенном сайте с помощью PHP?
Я пытаюсь перенести изображения для своего сайта с моего хоста на облачный хостинг Amazon S3. Эти изображения являются клиентскими рабочими сайтами и не могут быть общедоступными. Я бы хотел, чтобы они отображались на моем сайте, предпочтительно, используя PHP SDK, доступный из Amazon.
До сих пор мне удалось преобразовать script, чтобы я просматривал записи в своей базе данных, хватал путь к файлу, правильно назвал его и отправлял в 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 />
Используя этот метод, как будет работать мое кеширование? Я предполагаю, что каждый раз, когда я обновляю страницу или изменяю одну из своих записей, я снова буду тянуть это изображение, увеличивая мои запросы на получение.
Я также рассмотрел использование политик bucket, чтобы разрешить поиск изображений у определенных источников. Правильно ли я понимаю, что Amazon должен получать только запросы со страниц или доменов, которые я указываю?
Я ссылался:
https://forums.aws.amazon.com/thread.jspa?messageID=188183𭼗, чтобы установить это, но тогда я запутался в отношении какой мне безопасности на моих объектах. Похоже, если бы я сделал их частными, они все равно не отобразились бы, если бы я не использовал ссылку temp, как упоминалось ранее. Если бы я сделал их общедоступными, я мог бы перейти к ним напрямую, независимо от источника.
Неужели я отсюда то, что я пытаюсь сделать здесь? Разве это не поддерживается S3, или я пропустил что-то простое? Я прошел через SDK-документацию, и многие поиски и такие чувства должны быть более четко документированы, поэтому, надеюсь, любой вклад здесь может помочь другим в этой ситуации. Я читал других, которые называют файл уникальным идентификатором, создавая защиту через неизвестность, но это не сократит его в моей ситуации и, вероятно, не рекомендуется для тех, кто пытается быть в безопасности.
Ответы
Ответ 1
Лучший способ обслуживания изображений - генерировать URL-адрес с помощью PHP SDK. Таким образом, загрузка идет напрямую от S3 к вашим пользователям.
Вам не нужно загружать через серверы, как предлагалось в @mfonda - вы можете установить любые заголовки кеширования, которые вам нравятся на объектах S3, - и если бы вы это сделали, вы потеряли бы некоторые основные преимущества использования S3.
Однако, как вы указали в своем вопросе, url всегда будет меняться (на самом деле querystring), поэтому браузеры не будут кэшировать файл. Легкая работа - это просто всегда использовать ту же дату истечения срока действия, чтобы всегда генерировалась одна и та же последовательность. Или еще лучше "кешировать" URL-адрес (например, в базе данных) и повторно использовать его каждый раз.
Очевидно, вам нужно установить время истечения срока действия где-то далеко в будущем, но вы можете регенерировать эти URL-адреса так часто, если хотите. например, в вашей базе данных вы сохранили бы сгенерированный URL-адрес и дату истечения срока действия (вы также можете проанализировать это из URL-адреса). Затем либо вы используете существующий url, либо, если дата истечения срока действия прошла, сгенерируйте новый. и т.д...
Ответ 2
Вы можете использовать политики ведра в своем ковше Amazon, чтобы ваш домен приложения мог получить доступ к файлу. Фактически, вы даже можете добавить свой локальный домен dev (например: 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/*"
]
}
}
}
]
}
Ответ 3
Когда вы говорите о безопасности и защите данных от неавторизованных пользователей, что-то ясно: вы должны проверять каждый раз, когда получаете доступ к этому ресурсу, на который вы имеете право.
Это означает, что генерирование URL-адреса, к которому может обратиться любой (может быть трудно получить, но все же...). Единственное решение - прокси изображения. Вы можете сделать это с помощью php script.
В блоге 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');
Ответ 4
Вы можете загрузить содержимое с S3 (в PHP script), а затем использовать их с помощью правильных заголовков.
Как пример, скажем, в 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">