즉석에서 이미지 크기 조정

이미지를 사용하는 거의 모든 웹 애플리케이션에는 이러한 이미지의 작은 복사본을 만들어야 하며, 추가 이미지에 대한 여러 형식이 있는 경우가 많습니다.
기존 애플리케이션에 새로운 차원을 추가하면 골치 아픈 문제가 발생합니다. 따라서 작업은 다음과 같습니다.

태스크

요구 사항 목록을 표시해 보겠습니다.

  • 애플리케이션이 존재하는 동안 언제든지 애플리케이션에 추가 기능을 도입하지 않고 모든 형식의 추가 이미지를 즉시 생성합니다.
  • 모든 요청에 ​​대해 추가 이미지를 생성할 필요는 없습니다.
  • 지정되지 않은 형식의 추가 이미지를 생성하는 기능을 비활성화합니다.

마지막 요점은 첫 번째 요점과 약간 모순되기 때문에 설명하겠습니다. 이미지 생성을 공개하면 이미지 크기를 무한한 형식으로 조정하라는 요청이 대량으로 생성되어 사이트에 대한 공격이 발생할 가능성이 있으므로 이 취약점을 해결해야 합니다.

nginx 설치 구성

위의 요구 사항을 해결하려면 다음 nginx 모듈 세트가 필요합니다.

모듈 ngx_http_image_filter_module и ngx_http_secure_link_module 기본적으로 설치되지 않으므로 설치 구성 단계에서 지정해야 합니다. Nginx에:

phoinix@phoinix-work:~/src/nginx-0.8.29
$ ./configure --with-http_secure_link_module --with-http_image_filter_module

nginx 구성

호스트 구성에 새 항목을 추가합니다. 위치 일반 캐시 매개변수:

...
    proxy_cache_path /www/myprojects/cache levels=1:2 keys_zone=image-preview:10m;
...
    server {
...
        location ~ ^/preview/([cir])/(.+) {
        # Тип операции
            set                         $oper $1;
        # Параметры изображения и путь к файлу
            set                         $remn $2;
        # Проксируем на отдельный хост
            proxy_pass                  http://myproject.ru:81/$oper/$remn;
            proxy_intercept_errors      on;
            error_page                  404 = /preview/404;
        # Кеширование
            proxy_cache                 image-preview;
            proxy_cache_key             "$host$document_uri";
        # 200 ответы кешируем на 1 день
            proxy_cache_valid           200 1d;
        # остальные ответы кешируем на 1 минуту
            proxy_cache_valid           any 1m;
        }
        
        # Возвращаем ошибку
        location = /preview/404 {
            internal;
            default_type                image/gif;
            alias                       /www/myprojects/image/noimage.gif;
        }
...
    }
...

또한 구성에 새 호스트를 추가합니다.

server {
    server_name                     myproject.ru;
    listen                          81;

    access_log                      /www/myproject.ru/logs/nginx.preview.access_log;
    error_log                       /www/myproject.ru/logs/nginx.preview.error_log info;

    # Указываем секретное слово для md5
    secure_link_secret              secret;

    # Ошибки отправляем она отдельный location
    error_page                      403 404 415 500 502 503 504 = @404;

    # location Для фильтра size
    location ~ ^/i/[^/]+/(.+) {
        
        # грязный хак от Игоря Сысоева *
        alias                       /www/myproject.ru/images/$1;
        try_files                   "" @404;
    
        # Проверяем правильность ссылки и md5
        if ($secure_link = "") { return 404; }
        
        # Используем соответсвующий фильтр
        image_filter                size;
    }

    # По аналогии остальные location для других фильтров
    location ~ ^/c/[^/]+/(d+|-)x(d+|-)/(.+) {
        set                         $width  $1;
        set                         $height $2;
        
        alias                       /www/myproject.ru/images/$3;
        try_files                   "" @404;
    
        if ($secure_link = "") { return 404; }
    
        image_filter                crop  $width  $height;
    }
    
    location ~ ^/r/[^/]+/(d+|-)x(d+|-)/(.+) {
        set                         $width  $1;
        set                         $height $2;

        alias                       /www/myproject.ru/images/$3;
        try_files                   "" @404;

        if ($secure_link = "") { return 404; }

        image_filter                resize  $width  $height;
    }

    location @404 { return 404; }
}

결과적으로 다음 링크를 사용하여 추가 이미지를 얻을 수 있습니다.

* try_files — 공백과 러시아어 문자에 민감해서 버팀목을 만들어야 했습니다. 별명.

웹 애플리케이션에서 사용

웹 애플리케이션 수준에서 다음 절차를 수행할 수 있습니다(Perl).

sub proxy_image {
    use Digest::MD5     qw /md5_hex/;
    my %params = @_;
    my $filter = {
                    size    => 'i',
                    resize  => 'r',
                    crop    => 'c'            
                  }->{$params{filter}} || 'r';
    my $path = ($filter ne 'i' ?
                    ( $params{height} || '_' ) . 'x' . ( $params{width} || '_' ) . '/' :
                    ()
               ) . $params{source};
    my $md5 = md5_hex( $path . 'secret' );
    $path = '/preview/' . $filter . '/' . $md5 . '/' . $path;
    return $path;
}

my $preview_path = &proxy_image(
                    source  => 'image1.jpg',
                    height  => 100,
                    width   => 100,
                    filter  => 'resize'
                );

크기를 계산하는 것도 권장하지만 시사.

레이크

원본 이미지를 삭제하면 당연히 캐시가 무효화될 때까지 미리보기가 캐시에서 삭제되지 않으며, 저희의 경우 삭제 후 하루 동안 미리보기가 존재할 수 있지만 이것이 최대 시간입니다.

원래의

출처 : habr.com

코멘트를 추가