Pregunta

Necesito crear un usuario ejabberd a partir de un script PHP. También necesito poder agregar el nuevo usuario a una lista compartida predefinida.

¿Debo llamar a ejabberdctl usando exec() o hay una mejor manera?

¿Fue útil?

Solución

ejabberdctl es, con mucho, el más fácil en este caso específico. Las otras opciones son:

  • Implemente un cliente XMPP completo en PHP (!)

  • Implemente un módulo en Erlang que represente las solicitudes: PHP < - > la comunicación de Erlang tendría que ser a través de un socket y una gran cantidad de cálculo estaría involucrado (!)

Otros consejos

Aquí está mi solución final:

Gracias a el consejo de jldupont que ejabberdctl sería el solución más fácil, seguí adelante a través de los obstáculos que encontré y tengo una solución que funciona.

Por defecto, el usuario de apache no tiene los privilegios correctos para ejecutar con éxito sudo (y por una buena razón). Entonces, para que funcione, debe llamarlo con /etc/sudoers. Pero ... www-data requiere una contraseña, que presenta 2 problemas:

  1. El usuario de apache no tiene una contraseña.
  2. Incluso si lo hiciera, no hay forma de ingresarlo desde PHP.

Solución (para Ubuntu): agregue esta línea al final de <=>:

www-data ALL= (ejabberd) NOPASSWD: /usr/sbin/ejabberdctl

La ruta al archivo sudoers y ejabberdctl puede variar para otras distribuciones de Linux. Esto permite que el usuario de apache (<=>) ejecute solo <=> con privilegios elevados y sin requerir una contraseña.

Todo lo que queda es el 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>';
    }
?>

Seguridad

Es importante tener en cuenta que esto presenta un riesgo de seguridad significativo aunque solo permita que <=> ejecute un comando. Si utiliza este enfoque, debe asegurarse de proteger el código PHP detrás de algún tipo de autenticación para que nadie pueda ejecutarlo. Más allá de los riesgos de seguridad obvios, podría abrir su servidor a un ataque de denegación de servicio.

Encontré esta pregunta en 2016, hay formas mucho más fáciles de implementar esto que la respuesta aceptada y la más votada.

  1. Utilice una biblioteca PHP XMPP, siendo la más común:

https://github.com/fabiang/xmpp

  1. Si bien esta biblioteca no admite agregar un usuario fuera de la caja, puede extenderla muy fácilmente

aquí está la clase que escribí para agregar un usuario:

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);
    }
}
  1. Debe habilitar el registro en banda en el archivo ejabberd.cfg, ya que está denegado de forma predeterminada:
  

{acceso, registro, [{permitir, todos}]}.

Finalmente, aquí hay un código de muestra para usar esta clase:

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();
    }

La llamada a la biblioteca fallará si el servidor no tiene un certificado SSL válido. Coloque un certificado válido o reemplace esta parte en SocketClient.php con el fragmento a continuación

// 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
);

Si desea una forma limpia y segura de hacerlo utilizando PHP dentro del protocolo XMPP, le recomendaré trabajar con este script de ejemplo register_user.php . Este es un ejemplo que se puede encontrar dentro de Jaxl Biblioteca PHP.

Descargue la biblioteca Jaxl y úsela de la siguiente manera:

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 $

La forma más fácil de hacerlo es usando mod_xmlrpc, que le permite ejecutar los comandos ejabberdctl usando xmlrpc. Esto es fácil de usar con una biblioteca 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 );

He resuelto el problema con mod_register_web [ 1 , 2 ]. No requiere toneladas de código y, creo, es lo suficientemente seguro. mod_register_web proporciona una página html con un simple formulario POST para registrar un nuevo usuario.

Habilite el módulo en un receptor HTTP separado (en mi caso, el puerto 5281). Haga que este puerto esté disponible solo para solicitudes locales con & Quot; ip & Quot; parámetro.

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: {}

Ejemplo de solicitud:

curl -XPOST 127.0.0.1:5281/register/new -d 'username=lucky&host=vHost&password=test&password2=test'

La solicitud se puede ejecutar desde el código php con la biblioteca adecuada (que ya estaba en mi marco).

curl -XPOST 127.0.0.1:5281/api/register -d '{" user ": " lucky ", " host < !> quot;: " data.com ", " contraseña ": " prueba "} '

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top