Создайте пользователя ejabberd из PHP
Мне нужно создать пользователя ejabberd из PHP-скрипта. Мне также нужно иметь возможность добавить нового пользователя в заранее определенный общий список.
Должен ли я просто позвонить ejabberdctl
, используя exec()
, или есть лучший способ?
7 answers
Ejabberdctl, безусловно, самый простой в данном конкретном случае. Другие варианты:
Реализовать полный клиентский XMPP на PHP (!)
Реализуйте модуль в Erlang, который выполняет прокси-запросы: связь PHPErlang должна осуществляться через сокет, и потребуется много маршалинга (!)
Вот мое окончательное решение:
Благодаря совету jldupont, что ejabberdctl
было бы самым простым решением, я преодолел препятствия, с которыми столкнулся, и нашел рабочее решение.
По умолчанию пользователь apache не имеет прав доступа для успешного запуска ejabberdctl
(и по уважительной причине). Поэтому для того, чтобы он работал, вы должны вызвать его с помощью sudo
. Но... sudo
требуется пароль, что создает 2 проблемы:
- Пользователь apache не у вас есть пароль.
- Даже если бы это было так, нет способа ввести его из PHP.
Решение (для Ubuntu) - добавьте эту строку в конце /etc/sudoers
:
www-data ALL= (ejabberd) NOPASSWD: /usr/sbin/ejabberdctl
Путь к файлу sudoers и ejabberdctl может отличаться для других дистрибутивов Linux. Это позволяет пользователю apache (www-data
) запускать только ejabberdctl
с повышенными привилегиями и без необходимости ввода пароля.
Все, что осталось, это PHP-код:
<?php
$username = 'tester';
$password = 'testerspassword';
$node = 'myserver.com';
exec('sudo -u ejabberd /usr/sbin/ejabberdctl register '.$username.' '.$node.' '.$password.' 2>&1',$output,$status);
if($output == 0)
{
// Success!
}
else
{
// Failure, $output has the details
echo '<pre>';
foreach($output as $o)
{
echo $o."\n";
}
echo '</pre>';
}
?>
Безопасность
Важно отметить, что это делает представляют значительный риск для безопасности, даже если вы разрешаете выполнять только одну команду www-data
. Если вы используете этот подход, вам нужно убедиться, что вы защищаете PHP-код с помощью какой-либо аутентификации, чтобы не только кто-либо мог заставить его выполняться. Помимо очевидных угроз безопасности, это может открыть ваш сервер для атаки типа "Отказ в обслуживании".
Я столкнулся с этим вопросом в 2016 году, есть гораздо более простые способы реализовать это, чем принятый ответ и тот, за который проголосовали больше всего.
- Используйте PHP-библиотеку XMPP, наиболее распространенной из которых является:
Https://github.com/fabiang/xmpp
- Хотя эта библиотека не поддерживает добавление пользователя из коробки, вы можете очень легко расширить ее
Вот класс, который я написал для добавления пользователя:
use Fabiang\Xmpp\Util\XML;
/**
* Register new user
* @param string $username
* @param string $password
* @param string $email
* @package XMPP\Protocol
* @category XMPP
*/
class Register implements ProtocolImplementationInterface
{
protected $username;
protected $password;
protected $email;
/**
* Constructor.
*
* @param string $username
* @param string $password
* @param string $email
*/
public function __construct($username, $password, $email)
{
$this->username = $username;
$this->password = $password;
$this->email = $email;
}
/**
* Build XML message
* @return type
*/
public function toString()
{
$query = "<iq type='set' id='%s'><query xmlns='jabber:iq:register'><username>%s</username><password>%s</password><email>%s</email></query></iq>";
return XML::quoteMessage($query, XML::generateId(), (string) $this->username, (string) $this->password, (string) $this->email);
}
}
- Вы должны включить внутриполосный регистрация в файле ejabberd.cfg, так как по умолчанию она запрещена:
{доступ, регистрация, [{разрешить, все}]}.
Наконец, вот пример кода для использования этого класса:
private function registerChatUser($name, $password, $email)
{
$address = 'tcp://yourserverip:5222';
$adminUsername = 'youradmin';
$adminPassword = 'youradminpassword';
$options = new Options($address);
$options->setUsername($adminUsername)->setPassword($adminPassword);
$client = new Client($options);
$client->connect();
$register = new Register($name, $password, $email);
$client->send($register);
$client->disconnect();
}
Вызов библиотеки завершится ошибкой, если сервер не имеет действительного SSL-сертификата. Либо поместите действительный сертификат, либо замените эту деталь в SocketClient.php с приведенным ниже фрагментом
// call stream_socket_client with custom error handler enabled
$handler = new ErrorHandler(
function ($address, $timeout, $flags) {
$options = [
'ssl' => [
'allow_self_signed' => true,
'verify_peer_name' => false,
],
];
$context = stream_context_create($options);
return stream_socket_client($address, $errno, $errstr, $timeout, $flags, $context);
},
$this->address,
$timeout,
$flags
);
Если вам нужен чистый и безопасный способ сделать это с помощью PHP в рамках протокола XMPP, я рекомендую работать с этим примером скрипта register_user.php . Это пример, который можно найти внутри Библиотеки PHP Jaxl.
Загрузите библиотеку Jaxl и используйте ее следующим образом:
JAXL $ php examples/register_user.php localhost
Choose a username and password to register with this server
username:test_user
password:test_pass
registration successful
shutting down...
JAXL $
Самый простой способ сделать это - использовать mod_xmlrpc, который позволяет запускать команды ejabberdctl с помощью xmlrpc. Это легко использовать с такой библиотекой, как:
Https://github.com/gamenet/php-jabber-rpc
/* Add user to Jabber */
use \GameNet\Jabber\RpcClient;
use \GameNet\Jabber\Mixins\UserTrait;
$rpc = new RpcClient([
'server' => 'jabber.org:4560',
'host' => 'myhost.org',
'debug' => false,
]);
$result=$rpc->createUser( $username, $password );
Я решил проблему с помощью mod_register_web [1, 2]. Это не требует тонны кода и, я думаю, достаточно безопасно. mod_register_web предоставляет html-страницу с простой формой записи для регистрации нового пользователя.
Включите модуль в отдельном прослушивателе http (в моем случае, порт 5281). Сделайте этот порт доступным только для локальных запросов с параметром "ip".
listen:
port: 5280
module: ejabberd_http
web_admin: true
http_bind: true
## register: true
ip: "127.0.0.1" # Only local requests allowed for user registration
port: 5281
module: ejabberd_http
register: true
modules:
mod_register_web: {}
Пример запроса:
curl -XPOST 127.0.0.1:5281/register/new -d 'username=lucky&host=vHost&password=test&password2=test'
Запрос может быть выполнен из php-кода с соответствующей библиотекой (которая уже была в моей структуре).
Curl -XPOST 127.0.0.1:5281/api/register -d'{"пользователь": "счастливчик", "хост":"data.com ", "пароль": "тест"}'