Содержание
Если у вас есть какой-нибудь сайт с базой зарегистрированных пользователей, то вы можете легко предоставить своим постоянным посетителям Jabber адреса в вашем домене. В этой статье описан способ интеграции XMPP сервера с существующей базой пользователей.
Основная идея заключается в следующем:
- JID пользователя получается из его логина путём прибавление имени вашего домена. То есть если у вас домен domain.com, то у пользователя vasya будет JID vasya@domain.com. При этом надо учесть, что в JID могут использоваться любые символы, однако чаще всего JID ко всему прочему ассоциируются с почтовыми адресами, а в них уже могут использоваться только буквы латинского алфавита и символы «_-.», и при этом адреса нечувствительны к регистру. Как добавить в описываемую схему почту описано в отдельной статье. Чаще всего все эти ограничения прекрасно ложатся на существующие базы пользователей, но могут быть и исключения. Во многих движках у пользователя просто есть возможность сменить отображаемое имя, и при этом почти всегда имя нечувствительно к регистру. Это позволяет без проблем создавать почтовые адреса по описанной схеме пользователям, в них нуждающимся.
- Пароль на XMPP аккаунт пользователя будет совпадать с паролем пользователя на вашем сайте.
- Интеграция никак не должна затронуть возможности XMPP сервера, то есть вы будете вольны добавить на сервер любой дополнительный функционал, например, конференции и транспорты.
В результате пользователь получит полнофункциональный Jabber адрес со всем дополнительным функционалом, который вы поставите на свой сервер, совмещённый с его профилем на вашем сайте. При этом пользователю для доступа к вашему XMPP серверу не потребуется запоминать ни дополнительный логин, ни дополнительный пароль - они будут совпадать с его регистрационными данными на вашем сайте.
Практическая сторона вопроса
В качестве 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 примерно по такой же схеме можно подключить вашим пользователям почтовые адреса, этому посвящена отдельная статья: