Валидация клиентов по наличию JavaScript
Pavel Zhovner
pavel на zhovner.com
Сб Сен 24 10:32:26 UTC 2011
Здравствйте.
Задача пропускать к бекенду только клиентов с включенным javascript,
для этого на стороне клиента и сервера предполагается посчитать хеш на
основе ip клиента.
Для этого используется сторонний модуль ngx_http_set_hash и
аналогичная функция на javascript которая результат вычислений
записывает в cookie.
Алгоритм работы страницы с javascript такой: посчитать хеш из адреса,
занести результат в cookie с названием sha1, обновить страницу.
Конфиг выглядит так:
location / {
#Если нет cookie отправить на страницу с javascript
if ( $cookie_sha1 = "" ){
rewrite ^ /no_cookie.html last;
}
# Генирация хеша из ip
set_sha1 $sha1_hash $remote_addr;
set $twovars $cookie_sha1:$sha1_hash";
# Проверить правильность cookie sha1 в противном случаи
отправить на страницу с javascript
# конструкция с двумя переменными в одной использована потому,
что в nginx нельзя сравнить переменную с переменной
if ($twovars !~* "^(.*):\1$") {
rewrite ^ /bad_cookie.html last;
}
# Иначе отправить запрос бекенду
proxy_pass http://backend;
}
# location ведущие на страницы с javascript. (Разделены на две
чтобы логировать оба события)
location /no_cookie.html {
add_header Set-Cookie "addr=$remote_addr; path=/";
root /page/javascript;
internal;
access_log /log/rewrite.log nocookie;
}
location /bad_cookie.html {
add_header Set-Cookie "addr=$remote_addr; path=/";
root /page/javascript;
internal;
access_log /log/rewrite.log badcookie;
}
Такая конструкция полностью работоспособна и свою задачу выполняет.
Два отдельных локейшена no_cookie и bad_cookie созданы для того чтобы
логировать какой именно rewrite сработал, потому что access_log
помещенный перед действитем rewrite не записывает лог.
Покритикуйте пожалуйста такое решение и укажите на ошибки. Например
при срабатывании условия отсутвия куки (первый rewrite) будет ли
выполнено set_sha1, хотя по логике при срабатывании рерайта last будет
сразу выполнен выход из location /
Так же возможно ли организовать некое подобие white list чтобы не
считать хеш на каждый легитимный запрос, а после первого успешного
сравнения пропускать без проверки хеша? Например с помощью модуля
geoip.
Подробная информация о списке рассылки nginx-ru