parser

Защита от дублирования сообщений с использованием hashfile

Автор: Misha v.3 [10 марта 2005]
Версия: 1.13
Тэги: Спам

Основная идея данного метода защиты от дублирования постов следующая: при отображении формы добавления сообщения мы генерим уникальный UID и помещаем его в hidden поле и в hashfile на пару часов (мне кажется что пары часов достаточно чтобы сформулировать свою мысль и отправить её на сервер).

После того как пришли POST данные мы проверяем наличие в хешфайле записи с переданным UID, и если такая запись есть — добавляем сообщение и удаляем запись из хешфайла, в противном случае считаем что запись уже была добавлена ранее (двойное нажатие submit, reload) или она добавляется ручками без использования нашей формы (что нам не особенно нужно).

Ну а теперь сам код:

# путь где будут жить hashfile и lock-file
$data_dir[/../data]

# открываем хешфайл
$hashfile[^hashfile::open[$data_dir/_double]]

^if(def $form:uid){
	$uid[$form:uid]
}{
	^rem{ *** генерим uid и добавляем его в хешфайл на 2 часа *** }
	$uid[^math:uuid[]]
	$hashfile.[$uid][
		$.value[1]
		$.expires(2/24)
	]
}

$is_show_form(1)

^if(def $form:uid){
	^rem{ *** пришло $form:uid - постят данные *** }
	^file:lock[$data_dir/_lock]{
		^if(^hashfile.[$uid].int(0) == 1){
			^rem{ *** в хешфайле есть соответствующий uid - все ок, добавляем сообщение *** }
			...
			
			^rem{ *** удаляем обработаный ключ из хешфайла *** }
			^hashfile.delete[$uid]

			^rem{ *** пробегаем по всем записям чтобы очистились устаревшие *** }
			^hashfile.foreach[k;]{}

			<p>Ваше сообщение было успешно добавлено.</p>
		}{
			^rem{ *** э, князь, ты не прав: не знаем мы ничего про такой uid, до свидания *** }
			<p>Ваше сообщение уже было добавлено ранее.</p>
		}
		$is_show_form(0)
	}
}


^if($is_show_form){
	<form method="post" action="./">
		<input type="hidden" name="uid" value="$uid" />
		<i>Имя:</i><br />
		<input type="text" name="name" value="$form:name" /><br />
		<i>E-mail:</i><br />
		<input type="text" name="email" value="$form:email" /><br />
		<i>Сообщение:</i><br />
		<textarea name="text">$form:text</textarea>
		<br />
		<input type="submit" name="action" value="Отправить" />
	</form>
}

Использовать hashfile совершенно не обязательно. В качестве временного хранилища также можно использовать отдельную таблицу в БД (например heap), но с parser мне кажется применение для этих целей hashfile вполне оправданным.

Раньше для защиты от дублей я так-же пользовался hashfile, но хранил там в течении нескольких часов UID-ы записей, которые я уже добавил в БД. При таком методе в hashfile-е единовременно хранилось больше записей, к тому же не было защиты от некоторых примитивных спамеров, которые постят в форумы без открытия формы (более надежно от спама защищает другой класс, использующий описываемый тут механизм как одну из своих составных частей, поэтому в любом случае я рекомендую использовать его).

Возможен так же вариант защиты от дублирования когда UID-ы сохраняются в дополнительных столбцах таблиц гостевой/форума и т.п. с уникальным индексом, но мне подобный подход не нравится, т.к. подразумевает хранение достаточно большого количества совершенно ненужной впоследствии информации.

На самом деле можно было не читать то, что написано выше, а просто скачать класс к которому прилагается рабочий пример и делать по образу и подобию :)

Скачать:

antiflood.zip (20.04.2007  2,3 КБ)
Класс для защиты от дублирования с примером использования.