Русское сообщество fluxbb

Быстрый лёгкий надёжный форумный движок

Вы не вошли.

Объявление

Вы можете внести свой вклад в содержание сайта. Жертвователи попадут в почетную группу "Спонсоры". Поддержать сайт.

#1 2008-04-16 18:02:06

andreus
Гость

Универсальная интеграция punbb с любым движком

Ниже приводится пример универсальной интеграции форума с любым движком, в основе которой лежат простые http-запросы к скриптам. Скрипты, в свою очередь, регистрируют пользователей и логинят их.

Данный подход используется на http://pupser.ru (сам сайт сделан на Ruby On Rails).

Для интеграции нам требуются три скрипта:

  • [li]скрипт регистрации, принимает в качестве параметров логин пользователя, пароль, email и ip[/li][li]скрипт входа на форум, принимает в качестве параметров логин и пароль[/li][li]скрипт смены пароля, принимает в качестве параметров логин и новый пароль[/li]

Благодаря этим скриптам мы сможем синхронизировать пользователей сайта (движка) и пользователей форума, и обеспечивать единообразный вход на сайт и на форум (через сайт).

Чтобы данный подход был безопасным (только движок мог работать с пользователями форума), можно использовать либо защиту по ip (например, ip движка - 192.168.1.10, запросы к скриптам с других ip-адресов будут игнорироваться), либо защиту с магическим ключом (одним из параметров запроса передаётся магический ключ, он сверяется либо с хэш-функцией от других параметров запроса и заранее заданного слова, либо с содержимым базы).

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

Непосредственно примеры php-скриптов (исходим из того, что их надо поместить в подкаталог interface каталога форума):

Скрипт регистрации:
/forum/interface/register.php?username=...&password=...&magick_key=...&email=...&ip=...
[mono]
<?php

// request should contain
//   magick_key
//   username
//   password
//   email
//   ip

require_once('mkeys.inc.php');

if (!checkMagickKey($_REQUEST['username'], $_REQUEST['magick_key']))
{
  echo "ERROR: invalid magick key";
  exit();
}

define('PUN_ROOT', '../');
require_once PUN_ROOT.'config.php';
require_once PUN_ROOT.'include/dblayer/common_db.php';
require_once PUN_ROOT.'include/functions.php';

// registration

$edit = array(
  'pass' => $_REQUEST['password'],
  'name' => $_REQUEST['username'],
  'mail' => $_REQUEST['email'],
  'ip'   => $_REQUEST['ip']
);

$hash = pun_hash($edit['pass']);

$db->query(sprintf("INSERT INTO `".$db_prefix."users` (`username`,`password`,`email`,`registered`,`registration_ip`,`last_visit`, `style`)
        VALUES ('%s', '%s', '%s', %d, '%s', %d, 'wine')",
        $db->escape($edit['name']), $db->escape($hash), $db->escape($edit['mail']), time(), $edit['ip'], time()));

if ($db->affected_rows() == 1)
{
  echo "OK: $hash";
}
else
{
  echo "ERROR: failed to insert user";
}

?>
[/mono]

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

Скрипт входа на форум:
/forum/interface/login.php?username=...&hash=...&magick_key=...
[mono]
<?php

// request should contain
//   magick_key
//   username
//   hash (password hash)

require_once('mkeys.inc.php');

if (!checkMagickKey($_REQUEST['username'], $_REQUEST['magick_key']))
{
  header('Location: ../index.php');
  exit();
}

define('PUN_ROOT', '../');
require_once PUN_ROOT.'config.php';
require_once PUN_ROOT.'include/dblayer/common_db.php';
require_once PUN_ROOT.'include/functions.php';

// login

$edit = array(
  'hash' => $_REQUEST['hash'],
  'name' => $_REQUEST['username'],
);

$id = $db->result($db->query(
  sprintf("SELECT id FROM `".$db_prefix."users` WHERE `username` = '%s' AND `password` = '%s'",
    $db->escape($edit['name']), $db->escape($edit['hash']))
));

if ($id)
{
  pun_setcookie($id, $edit['hash'], time() + 31536000);
}

header('Location: ../index.php');

?>
[/mono]

Скрипт смены пароля:
/forum/interface/change_password.php?username=...&password=...&magick_key=...

[mono]
<?php

// request should contain
//   magick_key
//   username
//   password

require_once('mkeys.inc.php');

if (!checkMagickKey($_REQUEST['username'], $_REQUEST['magick_key']))
{
  echo "ERROR: invalid magick key";
  exit();
}

define('PUN_ROOT', '../');
require_once PUN_ROOT.'config.php';
require_once PUN_ROOT.'include/dblayer/common_db.php';
require_once PUN_ROOT.'include/functions.php';

// change pwd

$edit = array(
  'pass' => $_REQUEST['password'],
  'name' => $_REQUEST['username'],
  'mail' => '[email protected]',
  'ip'   => '127.0.0.1'
);

$hash = pun_hash($edit['pass']);

$db->query(sprintf("UPDATE `".$db_prefix."users` SET `password` = '%s' WHERE `username` = '%s'",
        $db->escape($hash), $db->escape($edit['name'])));

if ($db->affected_rows() == 1)
{
  echo "OK: $hash";
}
else
{
  // record not found, insert
  $db->query(sprintf("INSERT INTO `".$db_prefix."users` (`username`,`password`,`email`,`registered`,`registration_ip`,`last_visit`, `style`)
          VALUES ('%s', '%s', '%s', %d, '%s', %d, 'wine')",
          $db->escape($edit['name']), $db->escape($hash), $db->escape($edit['mail']), time(), $edit['ip'], time()));

  if ($db->affected_rows() == 1)
  {
    echo "OK: $hash";
  }
  else
  {
    echo "ERROR: failed to update user";
  }
}

?>
[/mono]

Если скрипт не найдёт пользователя, он создаст нового.

И, наконец, вспомогательный скрипт для проверки магического ключа:

[mono]
<?php

function checkMagickKey($username, $magickKey)
{
  $link = mysql_connect('localhost', 'dbuser', 'dbpassword');
  if (!$link)
  {
    return false;
  }
  mysql_select_db("integration", $link);
  $value = mysql_escape_string(md5($username . $magickKey . "otherkey"));
  $rs = mysql_query("SELECT id FROM magick_keys WHERE magick_key = '$value' AND"
    ." created_at > DATE_SUB(NOW(), INTERVAL 1 MINUTE)", $link);
  $row = mysql_fetch_row($rs);
  mysql_close($link);
  return $row ? true : false;
}

?>
[/mono]

Скрипт подключается к mysql-БД с именем integration, и ищет неустаревший магический ключ в таблице magick_keys.
Вы можете отключить проверку, просто возвращая из данной функции true.

Пример вызова скрипта регистрации из движка на Rails:
(вызывается URL /forum/interface/register.php?username=...&password=...&magick_key=...&email=...&ip=...)

[mono]
  def register(username, password, email, ip)
    key = Time.now.to_i.to_s
    m_key = Digest::MD5.hexdigest(username + key)
    magickKey = MagickKey.new(:magick_key => m_key, :created_at => Time.now)
    if magickKey.save
      Net::HTTP.start(FORUM_SITE) { |http|
        resp = http.get2(FORUM_REGISTER_URL + "?username=#{username}&password=#{password}&magick_key=#{key}&email=#{email}&ip=#{ip}")
       
        if resp.code == "200" && resp.body =~ /^OK\:\s(.+)$/
          self.password_hash = $1
        else
          self.password_hash = ""
        end
      }
    end
    self.password_hash
  end
[/mono]

p.s. php-скрипты написаны благодаря участникам данного форума, и их постам про интеграцию форума с разными системами.

Редактировался andreus (2008-04-16 18:06:55)

Подвал доски

Под управлением FluxBB. Хостинг Hostens