Новости Joomla на русском
Главная Новости Форум Статьи и обзоры Вопросы и Ответы
Joomla! по-русски

Выпущен очередной релиз безопасности — Joomla 1.5.15 [Wojmamni ama mamni]. В данной версии исправлено 60 ошибок, обнаруженных при тестировании Joomla 1.5.x (среди них две, связанные с безопасностью, но некритические). Разработчики настоятельно рекомендуют обновиться до данной версии.

 
четверг, 11 марта 2010 Главная arrow Статьи и обзоры arrow Улучшаем механизм оценки статей в Joomla
Категории
Статьи
Обзоры
Модификации и хаки
Joomla!™ CMS
Russian Joomla Translation Team
Безопасность
Популярные статьи

Замечание

Joomla!™ является торговой маркой компании Open Source Matters inc в США и др. странах. Название Joomla! и его вариации, такие как J, Joom и т.д., используются в рамках ограниченной лицензии, определённой компанией Open Source Matters. Проект Joomlaportal не относится к компании Open Source Matters или проекту Joomla! Точки зрения представленные на данном сайте не являются официальными точками зрения Joomla Project или Open Source Matters.

Торговая марка Joomla® и логотип используются в рамках ограниченной лицензии, предоставленной Open Source Matters.

Улучшаем механизм оценки статей в Joomla

08.08.2007 | smart | Забобрить эту страницу! | del.icio.us
Статьи и обзоры / Модификации и хаки

Стандартный компонент публикаций материалов Joomla поддерживает возможность оценки материалов посетителями сайта. Однако встроенный механизм оценки материала имеет существенный недостаток: он позволяет пользователям повторно оценивать материал. Ограничение конечно есть: нельзя подряд оценивать один и тот же материал с одного IP адреса, а вот поочередно два пользователя могут сколь угодно «накручивать» оценку. В этой статье я хочу рассказать о том, как можно немного улучшить механизм оценки и затруднить возможность «накрутки» рейтинга материала.

Для того, чтобы затруднить процесс накрутки рейтинга вполне достаточно будет запоминать IP-адрес не последнего оценившего материал пользователя, а всех, кто принял участие в оценке.

Для хранения данных о материалах и IP-адресах пользователей добавим дополнительную таблицу jos_content_rating_ext. Ее можно легко создать в phpMyAdmin.

CREATE TABLE `jos_content_rating_ext` (
  `content_id` int(11) NOT NULL DEFAULT '0',
  `user_id` int(11) NOT NULL DEFAULT '0',
  `rating` int(11) UNSIGNED NOT NULL DEFAULT '0',
  `ip` varchar(50) NOT NULL DEFAULT '',
   KEY `idx_content` (`content_id`, `ip`, `user_id`)
) TYPE=MyISAM;

Теперь модифицируем функцию сохранения результатов оценки статьи. Для этого необходимо открыть файл /components/com_content/content.php. Перед началом модификации рекомендую сделать резервную копию этого файла. Чтобы при желании можно было легко отменить внесенные изменения.

Итак, приступим. Находим в этом файле строчки:

function recordVote() {
     global $database;

и заменяем их на:

function recordVote() {
     global $database, $my;

Затем чуть ниже находим кусок кода:

 $query = "INSERT INTO #__content_rating ( content_id, lastip, rating_sum, rating_count )"
               . "\n VALUES ( " . (int) $cid . ", " . $database->Quote( $currip ) . ", " . (int) $user_rating . ", 1 )";
               $database->setQuery( $query );
               $database->query() or die( $database->stderr() );;

и после него добавляем:

               $query = "INSERT INTO #__content_rating_ext ( content_id, user_id, rating, ip )"
               . "\n VALUES ( " . (int) $cid . ", " . $my->id . ", " . (int) $user_rating . ", " . $database->Quote( $currip ) . " )";
               $database->setQuery( $query );
               $database->query() or die( $database->stderr() );

Затем еще чуть ниже находим код:

    } else {
 
      if ($currip != ($votesdb->lastip)) {
        $query = "UPDATE #__content_rating"
        . "\n SET rating_count = rating_count + 1, rating_sum = rating_sum + " . (int) $user_rating . ", lastip = " . $database->Quote( $currip )
        . "\n WHERE content_id = " . (int) $cid
        ;
        $database->setQuery( $query );
        $database->query() or die( $database->stderr() );

и заменяем его на:

    } else {
      $currip = ( phpversion() <= '4.2.1' ? @getenv( 'REMOTE_ADDR' ) : $_SERVER['REMOTE_ADDR'] );
      $query = "SELECT *"
      . "\n FROM #__content_rating_ext"
      . "\n WHERE content_id = " . (int) $cid
      . (($my->id) ? "\n AND user_id = " . $my->id : "\n AND ip = " . $database->Quote( $currip ) )
      ;
      $database->setQuery( $query );
      $cnt = $database->loadResult();
 
      if ($cnt == 0 ) {
        $query = "UPDATE #__content_rating"
        . "\n SET rating_count = rating_count + 1, rating_sum = rating_sum + " . (int) $user_rating . ", lastip = " . $database->Quote( $currip )
        . "\n WHERE content_id = " . (int) $cid
        ;
        $database->setQuery( $query );
        $database->query() or die( $database->stderr() );
 
        $query = "INSERT INTO #__content_rating_ext ( content_id, user_id, rating, ip )"
        . "\n VALUES ( " . (int) $cid . ", " . $my->id . ", " . (int) $user_rating . ", " . $database->Quote( $currip ) . " )";
        $database->setQuery( $query );
        $database->query() or die( $database->stderr() );

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

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

Однако, помимо положительных эффектов, есть и небольшая ложка дегтя. В наше время достаточно частое явление когда несколько пользователей выходят в интернет под одним внешним IP. И данная модификация позволит проголосовать только первому из группы пользователей этого адреса.

Частично эту проблему можно решить, предложив пользователям сначала авторизоваться на сайте. Потому как для авторизованных пользователей проверка производится не по IP, а по их идентификатору.

Желаю успешных экспериментов, жду отзывов и вопросов на форуме!

 
< Пред.   След. >
Загрузить Joomla!™ CMS
Демо версия

Joomla! 1.5.14 (FrontEnd)
Joomla! 1.5.14 (BackEnd)
(Demo/Demo)