Введение
Защита от ботов посредством капч на критичные действия пользователей. Красивую и сложную капчу генерить довольно ресурсоёмко и не всегда оправдано.
Задача
Защитить скачивание файла введением капчи.
Решение 1 — простое
Структура папок
/spool/projects/capcha/— root директорияfiles/— директория с файламиcapches/— директория с капчамиindex.html— индексный файл
index.html
<html>
<body>
<form action="/download" method="GET">
<!--#include virtual="/capches/"-->
<input type="text" name="code" value="">
<input type="submit">
</form>
</body>
</html> Файлы в папке capches
<img src="data:image/png;base64,...">
<input type="hidden" name="md5" value="IODn35yg2gLtnSRhyKyK6g">
<input type="hidden" name="key" value="5e12c2002a0370826a9dee5f6a55f5e3"> key — имя файла, md5 — MD5 сумма от комбинации ключа, кода и соли.
Конфиг nginx
server {
listen 80;
server_name capcha.local;
root /spool/projects/capcha/;
index index.shtml;
location / {
ssi on;
}
location /capches/ {
random_index on;
}
location /download {
proxy_pass %backend_uri%;
}
location /file {
deny all;
}
} Решение 2 — pure nginx
Это решение предлагается исключительно в ознакомительных целях.
Добавляем поле в форму:
<input type="hidden" name="file" value="arch1"> Символьная ссылка:
ln -s /spool/projects/capcha/capches /spool/projects/capcha/dav Конфигурация nginx
map $file_alias $filename {
default 'fail';
'arch1' 'archive1.zip';
'arch2' 'archive2.zip';
'arch3' 'archive3.zip';
}
server {
listen 80;
server_name captcha.local;
root /spool/projects/capcha/;
index index.shtml;
location / { ssi on; }
location /capches/ { random_index on; }
location /download {
if ($request_method != 'GET') { return 301 /fail; }
if ($arg_key !~ '^\w+$') { return 301 /fail; }
secure_link $arg_md5;
secure_link_md5 "$arg_key $arg_code salt";
if ($secure_link = "") { return 301 /fail; }
if ($secure_link = "0") { return 301 /fail; }
set $file_alias $arg_file;
proxy_intercept_errors on;
proxy_pass http://127.0.0.1/dav/$arg_key.html;
proxy_method DELETE;
proxy_set_header Host $host;
proxy_set_header X-File $filename;
}
location /dav/ {
allow 127.0.0.1;
deny all;
dav_methods DELETE;
add_header X-Accel-Redirect "/file/$http_x_file";
add_header Content-Disposition "attachment; filename=\"$http_x_file\"";
error_page 403 404 =301 /fail;
}
location /file {
internal;
try_files $uri =204;
}
location /fail {
return 200 'FAIL CODE';
}
} Заключение
Можно сделать статичную капчу и производить её валидацию прямо на уровне nginx, однако существуют трудности:
- Конкурентность при одновременном выборе одного файла разными пользователями.
- Необходимость постоянной прегенерации достаточного количества капч.
- Определённые сложности с масштабированием.