Создать измененный кэш изображений, но предотвратить злоупотребления

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

Ситуация:

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']);
}

?>
Другие вопросы по тегам