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

Основная идея заключается в следующем:

  1. JID пользователя получается из его логина путём прибавление имени вашего домена. То есть если у вас домен domain.com, то у пользователя vasya будет JID vasya@domain.com. При этом надо учесть, что в JID могут использоваться любые символы, однако чаще всего JID ко всему прочему ассоциируются с почтовыми адресами, а в них уже могут использоваться только буквы латинского алфавита и символы «_-.», и при этом адреса нечувствительны к регистру. Как добавить в описываемую схему почту описано в отдельной статье. Чаще всего все эти ограничения прекрасно ложатся на существующие базы пользователей, но могут быть и исключения. Во многих движках у пользователя просто есть возможность сменить отображаемое имя, и при этом почти всегда имя нечувствительно к регистру. Это позволяет без проблем создавать почтовые адреса по описанной схеме пользователям, в них нуждающимся.
  2. Пароль на XMPP аккаунт пользователя будет совпадать с паролем пользователя на вашем сайте.
  3. Интеграция никак не должна затронуть возможности XMPP сервера, то есть вы будете вольны добавить на сервер любой дополнительный функционал, например, конференции и транспорты.

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

Кроме Jabber в описываемую схему можно легко включить и собственный почтовый сервер, этому посвящена отдельная статья:

Практическая сторона вопроса

В качестве XMPP сервера будем использовать ejabberd. Он есть в стандартных репозиториях и его можно установить через любой пакетный менеджер. Например, командой:

sudo apt-get install ejabberd

Для интеграции с существующей БД пользователей всего лишь нужно сказать ejabberd использовать внешний механизм авторизации и написать модуль, реализующий авторизацию через вашу базу. Для использования внешней авторизации в конфигурационный файл ejabberd /etc/ejabberd/ejabberd.conf нужно записать всего лишь две строчки:

{auth_method, external}.
{extauth_program, "/etc/ejabberd/auth.pl"}.

Ну и собственно сам модуль авторизации, написанный на Perl, в данном примере для БД SMF, который вам потребуется отредактировать под вашу базу. Вам нужно будет изменить параметры подключения к базе, запрос на выборку нужных данных и функцию проверки соответствия пароля:

#!/usr/bin/perl
 
# Внешний модуль авторизации для ejabberd через
# базу SMF.
#
# Author: Vadim Nevorotin aka Malamut
 
use 5.010;
use Digest::SHA1 qw(sha1_hex);
use DBI;
 
#############################################################
 
# Настройки базы данных (MySQL)
$MYSQL_host = 'bd.yourdomain.com';
$MYSQL_port = '3306';
$MYSQL_user = 'postfix';
$MYSQL_pass = 'PASSW0RD';
$MYSQL_db = 'my_smf';
 
# Параметры SMF - группа пользователей с доступом к почте и префикс таблиц
$SMF_GID = '15';
$SMF_prefix = 'smf_';
 
# Обслуживаемый домен
$valid_domain = "yourdomain.com";
 
#############################################################
 
# Просто соединяемся с БД
sub db_connect {
	my $dbh = DBI->connect("DBI:mysql:$MYSQL_db:$MYSQL_host:$MYSQL_port",$MYSQL_user,$MYSQL_pass);
	return $dbh;
}
 
$dbh = db_connect;
 
# Это именно то, что вы видите. Бесконечный цикл, ага.
while(1) {
	# Получаем запрос от ejabberd
	my $nread = sysread STDIN, my $buf, 2;
	unless ($nread == 2) { exit }
	my $len = unpack "n", $buf;
	$nread = sysread STDIN, $buf, $len;
 
	my ($op,$user,$domain,$passwd) = split /:/, $buf;
 
	# Сложно сказать зачем, но фильтруем символы
	$passwd =~ s/[\n\r]//g;
 
	# Домен проверяет ejabberd, но на всякий случай
	die "о_О" if $valid_domain ne $domain;
 
	my $result = 0;
	## Для идентичности поведения с почтовой системой:
	# если имя пользователя содержит неразрешённые символы - пропускаем его
	# Разрешены любые буквы, цифры и символы ".", "-" и "_"
	if ($user =~ /^\w+[\w.\-_]*\w+$/) {
		# Пытаемся восстановить соединение, если оно сброшено
		unless ($dbh) { $dbh = db_connect }
		# Подготавливаем запрос если соединение установлено. При неудаче - сбрасываем соединение
		my $sth = $dbh->prepare("SELECT memberName, realName, passwd
				FROM ${SMF_prefix}members
				WHERE (ID_GROUP = $SMF_GID OR FIND_IN_SET($SMF_GID, additionalGroups)) AND realName = '$user'")
			or $dbh = undef if $dbh;
		# Выполняем запрос если соединение установлено. При неудаче - сбрасываем соединение
		$sth->execute() or $dbh = undef if $dbh;
 
		# Если соединение не сброшено
		if ($dbh) {
			# Получаем количество найденных строк
			my $num = $sth->rows();
			# Получаем ответ если он состоит ровно из одной строки
			my $row = $sth->fetchrow_hashref() if $num == 1;
 
			# Проверяем пароль или пользователя
			if ($op =~ /auth/i and $num == 1) {
				my $epass = sha1_hex(lc($row->{memberName}) . $passwd);
	   			$result = $epass eq $row->{passwd} ? 1 : 0;
	   		} elsif ($op =~ /isuser/i and $num == 1) {
	   			$result = exists $row->{memberName} ? 1 : 0;
	   		}
		}
	} else {
		$result = 0;
	}
 
	# Отправляем ответ для ejabberd
	my $out = pack "nn", 2, $result;
	syswrite STDOUT, $out;
}

Кроме этого стоит убрать из секции modules конфигурационного файла ejabberd модуль mod_register, поскольку зарегистрироваться на вашем Jabber сервере невозможно.

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

Дополнительные возможности

Кроме JID примерно по такой же схеме можно подключить вашим пользователям почтовые адреса, этому посвящена отдельная статья:

Ссылки