Создать измененный кэш изображений, но предотвратить злоупотребления
Итак, у меня есть идея о том, как я хочу обслуживать и кэшировать свои изображения. Я не знаю, является ли это правильным способом, но если это так, я бы хотел знать, как предотвратить злоупотребления.
Ситуация:
index.php
<img src="images/cache/200x150-picture_001.jpg" />
Изображения / кэш /.htaccess
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ images/image.php?f=$1 [L]
Выше проверяет, существует ли изображение, если нет, оно будет перезаписано в image.php
image.php PSEUDO code
получить высоту и ширину из имени файла
изменить размер и сохранить изображение в папке кэша
обслуживать изображение с типом содержимого и файлом чтения.
Таким образом, я пытаюсь уменьшить HTTP-запросы и нагрузку PHP с помощью файлов чтения. Браузер получает изображение / JPEG, если оно существует, а если нет, оно будет сгенерировано.
В конечном итоге все изображения будут кэшироваться и обрабатываться с правильной высотой и шириной, поэтому браузеры не будут загружать слишком большие изображения.
Единственный улов.. если вы измените URL изображения на разные размеры, вы можете заполнить сервер.
Я делаю это правильно, как правильно это сделать. Есть ли шанс остановить это?
Я знаю, что вся эта концепция кеширования была усовершенствована миллион раз, пожалуйста, просветите меня.
4 ответа
Некоторые подходы:
Сохраните массив разрешенных разрешений и проверьте, находится ли запрошенное разрешение в этом массиве. Недостаток: вы не можете быстро добавить разрешение без редактирования массива.
Если это в контексте CMS: разрешить создание новых образов (которые еще не находятся в кэше) только аутентифицированным пользователям; отклонить запрос в противном случае. Когда аутентифицированный пользователь добавляет изображение в CMS, он предварительно просматривает его, и при этом создается изображение с измененным размером. Недостаток: не совсем легко реализовать.
Не уверен, что я не опоздал с ответом, но почему бы вам просто не использовать для этого SLIR (Smart Lencioni Image Resizer)? Он может делать все, что вам нужно (включая кеширование и управление кешем), поэтому вы можете просто вставить его и использовать.
Кэширование является совершенно нетривиальной проблемой - ваше решение кажется разумным, но оно действительно открыто для преднамеренных и непреднамеренных атак типа "отказ в обслуживании". Это также не касается того, что происходит при изменении изображения - как удалить все изображения с измененным размером из кэша? Он не устанавливает заголовки кэша, чтобы разрешить "нисходящие" кэши. Это не связано с риском одновременной очистки всего кэша, что требует повторной генерации всех изображений в контексте HTTP-запроса, что может привести к значительному снижению производительности.
Вы смотрели на готовые решения, такие как модуль кэширования Apache?
Я просто делаю:
<img src="/thumbnail.php?thumb=mybigpicture.ext" ... />
И вот как я это делаю. Обратите внимание, что эта реализация масштабирует изображения вне зависимости от того, являются ли они шире, чем выше, или наоборот, и выполняет приличную работу по масштабированию в отличие от большинства попыток PHP.
<?php
function thumb_image($request = "") {
$cfgthumb['folder'] = "/images/cache";
$cfgthumb['height'] = 150;
$cfgthumb['width'] = 200;
$cfgthumb['error'] = "/images/error.jpg";
$cfgthumb['default'] = "/images/notfound.jpg";
$thumb = $cfgthumb['folder'] . "/" . md5($request);
header("Content-Type: image/jpeg");
if (is_readable($thumb)) echo file_get_contents($thumb);
elseif (is_readable($request)) {
$extension = strtolower(end(explode(".", $request)));
switch ($extension) {
case "gif":
$simage = imagecreatefromgif($request);
break;
case "jpeg":
case "jpg":
$simage = imagecreatefromjpeg($request);
break;
case "png":
$simage = imagecreatefrompng($request);
break;
}
if ($simage) {
$simage_width = imagesx($simage);
$simage_height = imagesy($simage);
if (($simage_width > $cfgthumb['width']) || ($simage_height > $cfgthumb['height'])) {
if ($simage_width > $simage_height) {
$dimage_width = $cfgthumb['width'];
$dimage_height = floor($simage_height * ($cfgthumb['width'] / $simage_width));
} else {
$dimage_width = floor($simage_width * ($cfgthumb['height'] / $simage_height));
$dimage_height = $cfgthumb['height'];
}
} else {
$dimage_width = $simage_width;
$dimage_height = $simage_height;
}
$dimage = imagecreatetruecolor($dimage_width, $dimage_height);
imagegammacorrect($simage, 2.2, 1.0);
imagecopyresampled($dimage, $simage, 0, 0, 0, 0, $dimage_width, $dimage_height, $simage_width, $simage_height);
imagegammacorrect($dimage, 1.0, 2.2);
imagejpeg($dimage, $thumb, 100);
imagejpeg($dimage, NULL, 100);
imagedestroy($simage);
imagedestroy($dimage);
} else echo file_get_contents($cfgthumb['error']);
} else echo file_get_contents($cfgthumb['default']);
}
?>