이미지를 사용하는 거의 모든 웹 애플리케이션에는 이러한 이미지의 작은 복사본을 만들어야 하며, 추가 이미지에 대한 여러 형식이 있는 경우가 많습니다.
기존 애플리케이션에 새로운 차원을 추가하면 골치 아픈 문제가 발생합니다. 따라서 작업은 다음과 같습니다.
태스크
요구 사항 목록을 표시해 보겠습니다.
- 애플리케이션이 존재하는 동안 언제든지 애플리케이션에 추가 기능을 도입하지 않고 모든 형식의 추가 이미지를 즉시 생성합니다.
- 모든 요청에 대해 추가 이미지를 생성할 필요는 없습니다.
- 지정되지 않은 형식의 추가 이미지를 생성하는 기능을 비활성화합니다.
마지막 요점은 첫 번째 요점과 약간 모순되기 때문에 설명하겠습니다. 이미지 생성을 공개하면 이미지 크기를 무한한 형식으로 조정하라는 요청이 대량으로 생성되어 사이트에 대한 공격이 발생할 가능성이 있으므로 이 취약점을 해결해야 합니다.
nginx 설치 구성
위의 요구 사항을 해결하려면 다음 nginx 모듈 세트가 필요합니다.
ngx_http_image_filter_module — 이미지 크기 조정용ngx_http_proxy_module - 캐싱용ngx_http_secure_link_module — 스팸으로부터 보호하기 위해
모듈 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; }
}
결과적으로 다음 링크를 사용하여 추가 이미지를 얻을 수 있습니다.
myproject.ru/preview/i [md5]/[이미지_경로]myproject.ru/preview/c [md5]/[크기]/[이미지_경로]myproject.ru/preview/r [md5]/[크기]/[이미지_경로]
* 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'
);
크기를 계산하는 것도 권장하지만 시사.
레이크
원본 이미지를 삭제하면 당연히 캐시가 무효화될 때까지 미리보기가 캐시에서 삭제되지 않으며, 저희의 경우 삭제 후 하루 동안 미리보기가 존재할 수 있지만 이것이 최대 시간입니다.