从 PHP 创建 ejabberd 用户

发布于 2024-08-08 22:08:13 字数 104 浏览 2 评论 0原文

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

我应该使用 exec() 调用 ejabberdctl 还是有更好的方法?

I need to create an ejabberd user from a PHP script. I also need to be able to add the new user to a predefined shared roster.

Should I just call ejabberdctl using exec() or is there a better way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

っ〆星空下的拥抱 2024-08-15 22:08:13

这是我的最终解决方案:

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

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

  1. apa​​che 用户没有密码。
  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 代码,以便不是任何人都可以执行它。除了明显的安全风险之外,它还可能使您的服务器遭受拒绝服务攻击。

Here's my final solution:

Thanks to jldupont's advice that ejabberdctl would be the easiest solution, I pressed on through the obstacles I ran into and have a working solution.

By default, apache's user doesn't have the right privileges to successfully run ejabberdctl (and for good reason). So in order for it to work, you have to call it with sudo. But... sudo requires a password, which presents 2 problems:

  1. The apache user doesn't have a password.
  2. Even if it did, there's no way to enter it from PHP.

Solution (for Ubuntu) - add this line at the end of /etc/sudoers:

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

The path to the sudoers file and ejabberdctl may vary for other Linux distros. This allows apache's user (www-data) to run only ejabberdctl with elevated privileges and without requiring a password.

All that's left is the PHP code:

<?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>';
    }
?>

Security

It's important to note that this does present a significant security risk even though you're only allowing one command to be run by www-data. If you use this approach, you need to make sure you protect the PHP code behind some sort of authentication so that not just anybody can make it execute. Beyond the obvious security risks, it could open your server up to a Denial of Service attack.

永言不败 2024-08-15 22:08:13

我在 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 证书,则库调用将失败。放置有效的证书,或使用以下代码片段替换 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
);

I came upon this question in 2016, there are much easier ways to implement this than the accepted answer and the highest voted one.

  1. Use an XMPP PHP library, the most common one being:

https://github.com/fabiang/xmpp

  1. While this library doesn't support adding a user out of the box, you can very easily extend it

here is the class I wrote for adding a user:

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. You must enable in-band registration in the ejabberd.cfg file, as it's denied by default:

{access, register, [{allow, all}]}.

Finally here is a sample code for using this class:

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

The library call will fail if the server does not have a valid SSL certificate. Either place a valid certificate, or replace this part in SocketClient.php with the below snippet

// 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
);
时光是把杀猪刀 2024-08-15 22:08:13

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

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

  • 在 Erlang 中实现一个代理请求的模块:PHP<-- >Erlang 通信需要通过套接字进行,并且会涉及大量的编组工作 (!)

ejabberdctl is by far the easiest in this specific case. The other options are:

  • Implement a full client XMPP in PHP (!)

  • Implement a module in Erlang that proxies the requests: the PHP<-->Erlang communication would need to be through a socket and lots of marshaling would be involved (!)

马蹄踏│碎落叶 2024-08-15 22:08:13

如果您想要在 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 $

If you want a clean and secure way of doing this using PHP within XMPP protocol, I will recommend working with this example script register_user.php. This is an example that can be found inside Jaxl PHP Library.

Download Jaxl library and use as follows:

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 $
塔塔猫 2024-08-15 22:08:13

最简单的方法是使用 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 );

The easiest way of doing this is using mod_xmlrpc - which allows you to run the ejabberdctl commands using xmlrpc. This is easy to use with a library such as:

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 );
毁我热情 2024-08-15 22:08:13

我已经使用 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 代码执行请求。

I've solved the problem with mod_register_web [1, 2]. It doesn't require tonnes of code and, I think, is secure enough. mod_register_web provides html page with simple POST form to register new user.

Enable module under separate http listener (in my case, port 5281). Make this port available only for local requests with "ip" parameter.

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 example:

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

Request can be executed from php code with appropriate library (which was already in my framework).

瞳孔里扚悲伤 2024-08-15 22:08:13
curl -XPOST 127.0.0.1:5281/api/register -d '{"user":"lucky","host":"data.com","password":"test"}'

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

我只是应用它并从 ejabber 文档中分析它,然后将其调整为在 ejabberd 配置 xml 上创建的 ejabberd url 路径

curl -XPOST 127.0.0.1:5281/api/register -d '{"user":"lucky","host":"data.com","password":"test"}'

To apply to php you can use standard curl
, and the code above is the most recent curl code contained in the unpublished ejabberd doc,

I just apply it and analyze it from the doc ejabber then I adjust it to the ejabberd url path created on the ejabberd config xml

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文