Canvi de mida de la imatge sobre la marxa

En gairebé qualsevol aplicació web que utilitzi imatges, és necessari crear còpies petites d'aquestes imatges i sovint hi ha diversos formats per a imatges addicionals.
Afegir noves dimensions a una aplicació existent també provoca alguns maldecaps. D'aquí la tasca:

Tasca

Denotem la llista de requisits:

  • Genera imatges addicionals de qualsevol format sobre la marxa sense introduir funcionalitats addicionals a l'aplicació en cap moment durant l'existència de l'aplicació;
  • No cal que es generin imatges addicionals a cada sol·licitud;
  • Desactiveu la possibilitat de generar imatges addicionals de formats no especificats.

Explicaré el darrer punt, perquè contradiu una mica el primer punt. Si fem oberta la generació de qualsevol imatge, aleshores hi ha la possibilitat d'un atac al lloc generant un gran nombre de sol·licituds per canviar la mida de la imatge en un nombre infinit de formats, per la qual cosa cal tancar aquesta vulnerabilitat.

Configuració de la instal·lació de nginx

Per resoldre els requisits anteriors necessitem el següent conjunt de mòduls nginx:

Mòduls ngx_http_image_filter_module и ngx_http_secure_link_module no estan instal·lats per defecte, per la qual cosa s'han d'especificar en l'etapa de configuració de la instal·lació nginx:

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

configuració nginx

Afegim un de nou a la configuració de l'amfitrió ubicació i paràmetres generals de la memòria cau:

...
    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;
        }
...
    }
...

També afegim un nou amfitrió a la configuració:

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; }
}

Com a resultat, es poden obtenir imatges addicionals mitjançant els enllaços següents:

* try_files — sensible als espais i als caràcters russos, així que vaig haver de fer-hi una crossa àlies.

Ús en una aplicació web

A nivell d'aplicació web, podeu fer el següent procediment (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'
                );

Encara que també recomanaria calcular les mides Vista prèvia.

Rake

En suprimir la imatge original, les previsualitzacions, naturalment, no s'eliminaran de la memòria cau fins que la memòria cau no s'invalidi, i en el nostre cas, les previsualitzacions poden existir durant un dia després de la supressió, però aquest és el temps màxim.

original

Font: www.habr.com

Afegeix comentari