Redimensionarea imaginii din mers

În aproape orice aplicație web care utilizează imagini, este nevoie de a crea copii mici ale acestor imagini și adesea există mai multe formate pentru imagini suplimentare.
Adăugarea de noi dimensiuni unei aplicații existente provoacă, de asemenea, unele dureri de cap. De aici sarcina:

Sarcină

Să notăm lista de cerințe:

  • Generați imagini suplimentare ale oricăror formate din mers fără a introduce funcționalități suplimentare în aplicație în orice moment în timpul existenței aplicației;
  • Nu este necesar să fie generate imagini suplimentare la fiecare solicitare;
  • Dezactivați capacitatea de a genera imagini suplimentare de formate nespecificate.

Voi explica ultimul punct, deoarece contrazice ușor primul punct. Dacă deschidem generarea oricăror imagini, atunci există posibilitatea unui atac asupra site-ului prin generarea unui număr mare de solicitări de redimensionare a imaginii într-un număr infinit de formate, așa că această vulnerabilitate trebuie închisă.

configurarea instalării nginx

Pentru a rezolva cerințele de mai sus avem nevoie de următorul set de module nginx:

module ngx_http_image_filter_module и ngx_http_secure_link_module nu sunt instalate implicit, deci trebuie specificate în etapa de configurare a instalării Nginx:

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

configurația nginx

Adăugăm unul nou la configurația gazdă locaţie și parametri generali de cache:

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

De asemenea, adăugăm o nouă gazdă la configurație:

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

Ca rezultat, imagini suplimentare pot fi obținute folosind următoarele link-uri:

* try_files — sensibil la spații și caractere rusești, așa că a trebuit să fac o cârjă cu alias.

Utilizați într-o aplicație web

La nivel de aplicație web, puteți efectua următoarea procedură (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'
                );

Deși aș recomanda și calcularea dimensiunilor avanpremieră.

Rake

La ștergerea imaginii originale, previzualizările, desigur, nu vor fi șterse din cache până când memoria cache este invalidată, iar în cazul nostru, previzualizările pot exista pentru o zi după ștergere, dar acesta este timpul maxim.

оригинал

Sursa: www.habr.com

Adauga un comentariu