Criar usuário ejabberd do PHP
Pergunta
Eu preciso criar um usuário ejabberd a partir de um script PHP. Eu também preciso ser capaz de adicionar o novo usuário para uma lista compartilhada predefinidos.
Eu deveria chamar ejabberdctl
usando exec()
ou há uma maneira melhor?
Solução
ejabberdctl é de longe o mais fácil neste caso específico. As outras opções são:
-
Implementar um XMPP cliente completo em PHP (!)
-
Implementar um módulo em Erlang que proxies os pedidos: - (!) Do PHP <> comunicação Erlang teria de ser através de uma tomada e lotes de empacotamento estaria envolvido
Outras dicas
Aqui está a minha solução final:
Graças à conselho de jldupont que ejabberdctl
seria a solução mais fácil , eu pressionou através dos obstáculos eu corri para dentro e ter uma solução de trabalho.
Por padrão, o usuário do apache não tem os privilégios corretos para ejabberdctl
executar com êxito (e com razão). Então, para que ele funcione, você tem que chamá-lo com sudo
. Mas ... sudo
requer uma senha, que apresenta 2 problemas:
- O usuário apache não tem uma senha.
- Mesmo se o fizesse, não há nenhuma maneira de inseri-lo a partir de PHP.
Solution (para Ubuntu) - adicione esta linha no final do /etc/sudoers
:
www-data ALL= (ejabberd) NOPASSWD: /usr/sbin/ejabberdctl
O caminho para o arquivo sudoers e ejabberdctl pode variar para outras distribuições Linux. Isso permite que o usuário do apache (www-data
) para executar apenas ejabberdctl
com privilégios elevados e sem a necessidade de uma senha.
Tudo o que resta é o código 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>';
}
?>
Segurança
É importante notar que este não apresentar um risco de segurança significativo, mesmo que você só está permitindo que um comando a ser executado por www-data
. Se você usar essa abordagem, você precisa ter certeza de que você proteger o código PHP para trás algum tipo de autenticação para que não qualquer pessoa pode fazê-lo executar. Além riscos de segurança óbvia, poderia abrir seu servidor até um ataque de negação de serviço.
deparei-me com esta questão em 2016, existem maneiras muito mais fácil de implementar isso do que a resposta aceita eo mais votado um.
- Use uma biblioteca XMPP PHP, o mais comum é:
https://github.com/fabiang/xmpp
- Embora esta biblioteca não suporta a adição de um usuário fora da caixa, você pode muito facilmente estendê-lo
aqui é a classe que escrevi para adicionar um usuário:
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);
}
}
- Você deve habilitar o registro em banda no arquivo ejabberd.cfg, como é negado por padrão:
{acesso, cadastre-se, [{permitem, todos}]}.
Finalmente aqui está um código de exemplo para usar essa classe:
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();
}
A chamada biblioteca falhará se o servidor não tem um certificado SSL válido. Ou colocar um certificado válido, ou substituir esta parte em SocketClient.php com o abaixo trecho
// 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
);
Se você quiser uma maneira limpa e segura de fazer isso usando o PHP no protocolo XMPP, vou recomendar trabalhar com este exemplo de script register_user.php . Este é um exemplo que pode ser encontrado no interior Jaxl PHP Library.
Fazer download da biblioteca Jaxl e uso da seguinte forma:
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 $
A maneira mais fácil de fazer isso é usando mod_xmlrpc - que lhe permite executar os comandos ejabberdctl usando xmlrpc. Isso é fácil de usar com uma biblioteca, tais como:
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 );
Eu já resolveu o problema com mod_register_web [ 1 , 2 ]. Ele não requer toneladas de código e, penso eu, é bastante seguro. mod_register_web fornece página html com formulário POST simples de registrar novo usuário.
Ativar módulo sob ouvinte http separado (no meu caso, a porta 5281). Faça esta porta disponível apenas para solicitações locais com o parâmetro "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: {}
Request exemplo:
curl -XPOST 127.0.0.1:5281/register/new -d 'username=lucky&host=vHost&password=test&password2=test'
Request pode ser executado a partir do código php com biblioteca adequada (que já estava no meu quadro).
onda -XPOST 127.0.0.1:5281/api/register -d '{ "user": "sorte", "host": "data.com", "password": "teste"}'