【问题标题】:Create ejabberd user from PHP从 PHP 创建 ejabberd 用户
【发布时间】:2010-12-10 06:13:03
【问题描述】:

我需要从 PHP 脚本创建一个 ejabberd 用户。我还需要能够将新用户添加到预定义的共享名册中。

我应该直接使用exec() 拨打ejabberdctl 还是有更好的方法?

【问题讨论】:

    标签: php xmpp ejabberd


    【解决方案1】:

    ejabberdctl 在这种特定情况下是迄今为止最简单的。其他选项是:

    • 在 PHP 中实现完整的客户端 XMPP (!)

    • 在 Erlang 中实现一个模块来代理请求:PHPErlang 通信需要通过套接字,并且会涉及到大量的编组 (!)

    【讨论】:

    • 嗯...我似乎在有限的权限(或其他东西)方面遇到了麻烦。每当我尝试使用exec() 运行ejabberdctl 命令时,我都会得到回复:erlexec: HOME must be set
    • 好的 - 明白了。我会尽快发布我的解决方案。感谢您的建议。
    • 能否提供链接或源代码以通过 PHP 脚本创建 ejabberd 用户。
    【解决方案2】:

    这是我的最终解决方案:

    感谢jldupont's adviceejabberdctl 将是最简单的解决方案,我克服了遇到的障碍并找到了可行的解决方案。

    默认情况下,apache 的用户没有正确的权限来成功运行ejabberdctl(这是有充分理由的)。所以为了让它工作,你必须用sudo来调用它。但是...sudo 需要密码,这会带来两个问题:

    1. apache 用户没有密码。
    2. 即使有,也无法从 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 代码,以便不只是任何人都可以使其执行。除了明显的安全风险外,它还可能使您的服务器面临拒绝服务攻击。

    【讨论】:

    • 将您的 sudo 行更改为 www-data ALL= (ejabberd) NOPASSWD: /usr/sbin/ejabberdctl,以便 ejabberdctl 不会以 root 身份运行,而是以用户 ejabberd 身份运行。在您的代码中执行ejabberdctl,如下所示:sudo -u ejabberd ejabberdctl
    • 我在 linux 中遇到的相同问题,(错误:sh:/bin/su:权限被拒绝),解决方案(适用于 Ubuntu) - 在 /etc/sudoers 末尾添加此行:如何在linux中添加?
    • @Purushottam:Ubuntu 是一个基于 debian 的 linux 发行版。每个 linux 发行版都有自己的做事方式。我建议在您的特定 Linux 发行版中搜索 sudoers 文件的位置。
    • 我试过谷歌搜索,但仍然无法做到。我正在使用 CentOS linux 发行版,你能帮帮我吗?
    • 出现错误,例如,您正在尝试运行需要管理权限的“ejabberdctl”,但需要更多信息才能执行此操作。以“root”身份验证密码:密码:密码:
    【解决方案3】:

    如果您想在 XMPP 协议中使用 PHP 以一种干净且安全的方式执行此操作,我建议您使用此示例脚本 register_user.php。这是一个可以在Jaxl PHP 库中找到的示例。

    下载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 $
    

    【讨论】:

      【解决方案4】:

      最简单的方法是使用 mod_xmlrpc - 它允许您使用 xmlrpc 运行 ejabberdctl 命令。这很容易与以下库一起使用:

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

      【讨论】:

      • 我尝试了上面的方法,但它抛出了以下错误 传递给 fXmlRpc\Transport\HttpAdapterTransport::__construct() 的参数 1 必须是 Http\Message\MessageFactory 的实例,Ivory 的实例\HttpAdapter\CurlHttpAdapter 给定,在第 140 行的 /var/www/html/php-jabber-rpc/lib/GameNet/Jabber/RpcClient.php 中调用
      【解决方案5】:

      我在 2016 年遇到了这个问题,实现这个问题的方法比接受的答案和投票最高的答案要简单得多。

      1. 使用 XMPP PHP 库,最常见的是:

      https://github.com/fabiang/xmpp

      1. 虽然此库不支持开箱即用添加用户,但您可以非常轻松地对其进行扩展

      这是我为添加用户编写的类:

      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. 您必须在 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 证书,库调用将失败。要么放置一个有效的证书,要么用下面的 sn-p 替换 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
      );
      

      【讨论】:

      • 我尝试做同样的事情,但出现如下错误。在 ****/***/vendor/fabiang/xmpp/src/Connection/AbstractConnection.php:308 中未捕获的异常 'Fabiang\Xmpp\Exception\TimeoutException' 并带有消息 'Connection lost after 20 seconds'
      • 我收到此错误无法启用加密致命错误:未捕获异常'Fabiang\Xmpp\Exception\ErrorException'
      • @lakshmaji 我认为这可以通过答案的最后一步来解决,即更新 SocketClient.php 的部分
      • @AmrH.AbdelMajeed ,我已将现有代码替换为您答案中的最后一步,同样的错误,
      • 这对我来说不会产生任何问题,但它不会在 ejabberd 中创建任何用户,所以你有任何调试点吗?
      【解决方案6】:

      我已经用 mod_register_web [1, 2] 解决了这个问题。它不需要大量代码,而且我认为它足够安全。 mod_register_web 提供带有简单 POST 表单的 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: (52) Empty reply from server
      • "为什么要在上面的例子中设置两个密码??" - 因为它使用了网页也使用的用户注册的 POST 方法。两个密码字段对应注册表的“密码”和“验证密码”
      【解决方案7】:
      curl -XPOST 127.0.0.1:5281/api/register -d '{"user":"lucky","host":"data.com","password":"test"}'
      

      要适用于 php,您可以使用标准 curl ,而上面的代码是未发布的ejabberd doc中包含的最新curl代码,

      我只是应用它并从 doc ejabber 中对其进行分析,然后将其调整为在 ejabberd config xml 上创建的 ejabberd url 路径

      【讨论】:

      • 虽然此代码可能会回答问题,但提供有关它如何和/或为什么解决问题的额外上下文将提高​​答案的长期价值。
      • 提交完整的json格式 curl '{"user", "lucky", "master": "data.com", "password", "test"}' 都必须调整为现有 ejabberd doc 上现有语言和数据的格式
      • 当我在上面运行命令时: curl: (52) 来自服务器的空回复
      • 您的ejabber数据可能有错误,也可能是其他问题,请重新检查
      猜你喜欢
      • 2013-01-27
      • 1970-01-01
      • 2013-10-03
      • 1970-01-01
      • 1970-01-01
      • 2016-01-14
      • 1970-01-01
      • 1970-01-01
      • 2016-10-24
      相关资源
      最近更新 更多