Статья о том, как устроить на сайте голосование так, чтобы
* посетители из баловства не голосовали по несколько раз,
* разработчик приложил минимум усилий.
Итак, есть посетители со статическими и динамическими IP-адресами. Часто человек имеет доступ к нескольким компьютерам с интернетом. В интернет-кафе и школьных классах информатики компьютеры находятся в общественном пользовании.
Некоторые люди пользуются разными браузерами в зависимости от настроения, другие умеют менять IP-адреса как перчатки. Таких относительно редких чудес достаточно много.
Что важно? За одну условную сессию посетитель не должен проголосовать несколько раз.
Конечно, есть еще пожелания. Хорошо бы, человек, проголосовав на работе и придя домой, не кликнул бы еще разочек. То же относится и к счастливому обладателю модема, у которого на самом интересном месте разорвалось соединение. Два человека из-за одного компьютера в интернет-кафе не должны «склеиваться». И таких пожеланий много.
Соотношение между важным требованием и мини-пожеланиями — двадцать к одному.
Базовые решения
1. Никакой защиты можно не делать вообще. Вариант — мечта для программиста. Но доверие к результатам опроса исчезнет, если посетитель увидит, что голосовать можно сколько угодно раз. Поэтому хочется, чтобы человек кликнул и увидел, что второй раз не получится.
2. Делаем PHP-сессию и фиксируем факты голосования. В базу ничего не пишем. Что плохого? Если у администратора возникнут сомнения в достоверности результатов, расследования не получится. Да и сессия может закрыться, а посетитель вдруг вернется.
3. Есть еще подход без использования базы данных с куки. Здесь вообщее всё можно решить на клиентской стороне. Но у пользователя JavaScript и куки могут быть отключены. И расследования опять же не получится, случись что.
4. Записываем IP-адреса всех участников голосования и время. Делаем так, чтобы с одного адреса можно было голосовать раз в час. Недостатки? Никак не решается проблема с динамическими адресами. Зато нечистую игру уже можно разглядеть.
Именно так устроен модуль Drupal Voting. Для незарегистрированных посетителей других ограничений нет. Этот вариант я считаю сбалансированным — неплохой результат при небольших трудовых затратах. Дальше его можно улучшать.
Вообще-то есть еще вариант с сохранением в куки уникального идентификатора и записью его в базу. Но если бы мне пришлось выбирать, я бы лучше работал с IP-адресами. Проблема куки — доступность. IP-адрес поменять сложнее, чем стереть куки.
Дополнительные меры
1. IP-адрес можно доставать не из $_SERVER['REMOTE_ADDR'], а похитрее.
2. Если работать и с IP, и с куки, ситуация с динамическими адресами немного улучшится.
3. При голосовании можно спрашивать у посетителя какой-нибудь идентификатор, например, email или OpenID. Это шанс решить проблему с несколькими компьютерами и одним пользователем. Минус — посетителю нужно заполнять дополнительное поле.
4. Голосование можно сделать на AJAX. Плюс — отсеются боты, неумеющие исполнять JavaScript. Недостаток — поддержка JavaScript у некоторых пользователей выключена. И да, есть браузеры типа Opera 7.
5. Денис Болтиков предлагает продолжать работу с IP, используя базы адресов с разбивкой по странам и городам. Можно закрыть доступ всем нерусским посетителям, и заодно большинству анонимных прокси. Еще есть mod_geo.
6. Денис также говорит, что существуют готовые недорогие базы адресов анонимных прокси. А Dead Krolik советует ничего не покупать, а завести собственный черный список.
Я бы начинал с варианта «IP + задержка по времени + AJAX» и по мере необходимости добавлял бы разные защитки.
Кстати, любые дополнения и замечания очень приветствуются.
Дмитрий Сергеев, 21 год. Разрабатываю сайты на Drupal и CakePHP.
Юрий, 23.05.2007 09:07
Привет, Дима!
Интересная у вас с товарищами дискуссия в каментах разгорелась по поводу технологической части.
Но я так и не понимаю зачем нужны голосовалки? Как правило, большинство тыркает их просто так, не вдумываясь (сужу по себе и знакомым).
Да и вообще крутые парни должны быть крутыми сами по себе, а не слушать всех подряд (это я понял по хабрахабру, где каждый в каментах стремится поумничать, но не сказать ничего по делу).
А если уж нужно общественное мнение — нужно опрашивать дедовскими методами 8))
Всем удачи и свежего ветерка... А то эти +30 мне....