棘轮客户端身份验证失败

时间:2021-04-11 12:48:22

标签: php ratchet

我是网络套接字编程的新手。我正在 codeigniter 中实现网络套接字以实现简单的聊天功能,我的配置如下

 $config['ratchet_client'] = array(
    'host' => '127.0.0.1',    // Default host
    'port' => 8282,         // Default port (be careful to set unused server port)
    'auth' => true,         // If authentication is mandatory
    'debug' => true         // Better to set as false in Production
);

现在当我在终端上启动服务器时它显示

Running server on host 127.0.0.1:8282
Authentication activated

但是当我加载 html 时,它会在终端上显示以下内容

New client connected as (81)
Client (81) authentication failure
Client (81) authentication success
Client (81) disconnected

一次所有四行,在我的控制台上,我收到以下消息

enter image description here

更新我的 Ratchet_client.php(在库文件夹中)是

<?php

defined('BASEPATH') or exit('No direct script access allowed');

// Namespaces
use Ratchet\Http\HttpServer;
use Ratchet\Server\IoServer;
use Ratchet\WebSocket\WsServer;
use Ratchet\ConnectionInterface;
use Ratchet\MessageComponentInterface;

/**
 * @package   CodeIgniter Ratchet WebSocket Library: Main class
 * @category  Libraries
 * @author    Romain GALLIEN <romaingallien.rg@gmail.com>
 * @license   http://opensource.org/licenses/MIT > MIT License
 * @link      https://github.com/romainrg
 *
 * CodeIgniter library who allow you to make powerful applications with realtime interactions by using Websocket technology and Ratchetphp
 */
class Ratchet_client
{
    /**
     * CI Super Instance
     * @var array
     */
    private $CI;

    /**
     * Default host var
     * @var string
     */
    public $host = null;

    /**
     * Default host var
     * @var string
     */
    public $port = null;

    /**
     * Default auth var
     * @var bool
     */
    public $auth = false;

    /**
     * Default debug var
     * @var bool
     */
    public $debug = false;

    /**
     * Auth callback information
     * @var array
     */
    public $callback = array();

    /**
     * Config vars
     * @var array
     */
    protected $config = array();

    /**
     * Define allowed callbacks
     * @var array
     */
    protected $callback_type = array('auth', 'event');

    /**
     * Class Constructor
     * @method __construct
     * @param array $config Configuration
     * @return void
     * @author Romain GALLIEN <romaingallien.rg@gmail.com>
     */
    public function __construct(array $config = array())
    {
        // Load the CI instance
        $this->CI = &get_instance();

        // Load the class helper
        $this->CI->load->helper('ratchet_client');

        // Define the config vars
        $this->config = (!empty($config)) ? $config : array();

        // Config file verification
        if (empty($this->config)) {
            output('fatal', 'The configuration file does not exist');
        }

        // Assign HOST value to class var
        $this->host = (!empty($this->config['ratchet_client']['host'])) ? $this->config['ratchet_client']['host'] : '';

        // Assign PORT value to class var
        $this->port = (!empty($this->config['ratchet_client']['port'])) ? $this->config['ratchet_client']['port'] : '';

        // Assign AUTH value to class var
        //$this->auth = (!empty($this->config['ratchet_client']['auth'] && $this->config['ratchet_client']['auth'])) ? true : false;

        // Assign DEBUG value to class var
        $this->debug = (!empty($this->config['ratchet_client']['debug'] && $this->config['ratchet_client']['debug'])) ? true : false;
    }

    /**
     * Launch the server
     * @method run
     * @return string
     * @author Romain GALLIEN <romaingallien.rg@gmail.com>
     */
    public function run()
    {
        // Initiliaze all the necessary class
        $server = IoServer::factory(
            new HttpServer(
                new WsServer(
                    new Server()
                )
            ),
            $this->port,
            $this->host
        );

        // Run the socket connection !
        $server->run();
    }

    /**
     * Define a callback to use auth or event callback
     * @method set_callback
     * @param array $callback
     * @return void
     * @author Romain GALLIEN <romaingallien.rg@gmail.com>
     */
    public function set_callback($type = null, array $callback = array())
    {
        // Check if we have an authorized callback given
        if (!empty($type) && in_array($type, $this->callback_type)) {

            // Verify if the method does really exists
            if (is_callable($callback)) {

                // Register callback as class var
                $this->callback[$type] = $callback;
            } else {
                output('fatal', 'Method ' . $callback[1] . ' is not defined');
            }
        }
    }
}

/**
 * @package   CodeIgniter Ratchet WebSocket Library: Server class
 * @category  Libraries
 * @author    Romain GALLIEN <romaingallien.rg@gmail.com>
 * @license   http://opensource.org/licenses/MIT > MIT License
 * @link      https://github.com/romainrg
 *
 * CodeIgniter library who allow you to make powerfull applications with realtime interactions by using Websocket technology and Ratchetphp
 */
class Server implements MessageComponentInterface
{
    /**
     * List of connected clients
     * @var array
     */
    protected $clients;

    /**
     * List of subscribers (associative array)
     * @var array
     */
    protected $subscribers = array();

    /**
     * Class constructor
     * @method __construct
     * @author Romain GALLIEN <romaingallien.rg@gmail.com>
     */
    public function __construct()
    {
        // Load the CI instance
        $this->CI = &get_instance();

        // Initialize object as SplObjectStorage (see PHP doc)
        $this->clients = new SplObjectStorage;

        // // Check if auth is required
        if ($this->CI->ratchet_client->auth && empty($this->CI->ratchet_client->callback['auth'])) {
            output('fatal', 'Authentication callback is required, you must set it before run server, aborting..');
        }

        // Output
        if ($this->CI->ratchet_client->debug) {
            output('success', 'Running server on host ' . $this->CI->ratchet_client->host . ':' . $this->CI->ratchet_client->port);
        }

        // Output
        if (!empty($this->CI->ratchet_client->callback['auth']) && $this->CI->ratchet_client->debug) {
            output('success', 'Authentication activated');
        }
    }

    /**
     * Event trigerred on new client event connection
     * @method onOpen
     * @param ConnectionInterface $connection
     * @return string
     * @author Romain GALLIEN <romaingallien.rg@gmail.com>
     */
    public function onOpen(ConnectionInterface $connection)
    {

        // Add client to global clients object
        $this->clients->attach($connection);

        // Output
        if ($this->CI->ratchet_client->debug) {
            output('info', 'New client connected as (' . $connection->resourceId . ')');
        }
    }

    /**
     * Event trigerred on new message sent from client
     * @method onMessage
     * @param ConnectionInterface $client
     * @param string $message
     * @return string
     * @author Romain GALLIEN <romaingallien.rg@gmail.com>
     */
    public function onMessage(ConnectionInterface $client, $message)
    {
        // Broadcast var
        $broadcast = false;

        // Check if received var is json format
        if (valid_json($message)) {

            // If true, we have to decode it
            $datas = json_decode($message);
        }

        // Once we decoded it, we check look for global broadcast
        $broadcast = (!empty($datas->broadcast) and $datas->broadcast == true) ? true : false;

        // Count real clients numbers (-1 for server)
        $clients = count($this->clients) - 1;

        // Here we have to reassign the client ressource ID, this will allow us to send message to specified client.
        if (!empty($datas->user_id) && $datas->user_id !== $client->resourceId) {

            // At this moment we have to check if we have authent callback defined
            if (!empty($this->CI->ratchet_client->callback['auth']) && empty($client->subscriber_id)) {

                // Call user personnal callback
                $auth = call_user_func_array($this->CI->ratchet_client->callback['auth'], array($datas));

                // Verify authentication
                if (empty($auth) or !is_integer($auth)) {
                    output('error', 'Client (' . $client->resourceId . ') authentication failure');

                    // Closing client connexion with error code "CLOSE_ABNORMAL"
                    $client->close(1006);
                }

                // Add UID to associative array of subscribers
                $client->subscriber_id = $auth;

                // Output
                if ($this->CI->ratchet_client->debug) {
                    output('success', 'Client (' . $client->resourceId . ') authentication success');
                }
            }
        }

        // Now this is the management of messages destinations, at this moment, 4 possibilities :
        // 1 - Message is not an array OR message has no destination (broadcast to everybody except us)
        // 2 - Message is an array and have destination (broadcast to single user)
        // 3 - Message is an array and don't have specified destination (broadcast to everybody except us)
        // 4 - Message is an array and we want to broadcast to ourselves too (broadcast to everybody)
        if (!empty($message)) {

            // We look around all clients
            foreach ($this->clients as $user) {

                // Broadcast to single user
                if (!empty($datas->recipient_id)) {
                    if ($user->subscriber_id == $datas->recipient_id) {
                        $this->send_message($user, $message, $client);
                        break;
                    }
                } else {
                    // Broadcast to everybody
                    if ($broadcast) {
                        $this->send_message($user, $message, $client);
                    } else {
                        // Broadcast to everybody except us
                        if ($client !== $user) {
                            $this->send_message($user, $message, $client);
                        }
                    }
                }
            }
        }
    }

    /**
     * Event triggered when connection is closed (or user disconnected)
     * @method onClose
     * @param ConnectionInterface $connection
     * @return string
     * @author Romain GALLIEN <romaingallien.rg@gmail.com>
     */
    public function onClose(ConnectionInterface $connection)
    {
        // Output
        if ($this->CI->ratchet_client->debug) {
            output('info', 'Client (' . $connection->resourceId . ') disconnected');
        }

        // Detach client from SplObjectStorage
        $this->clients->detach($connection);
    }

    /**
     * Event trigerred when error occured
     * @method onError
     * @param ConnectionInterface $connection
     * @param Exception $e
     * @return string
     * @author Romain GALLIEN <romaingallien.rg@gmail.com>
     */
    public function onError(ConnectionInterface $connection, \Exception $e)
    {
        // Output
        if ($this->CI->ratchet_client->debug) {
            output('fatal', 'An error has occurred: ' . $e->getMessage());
        }

        // We close this connection
        $connection->close();
    }

    /**
     * Function to send the message
     * @method send_message
     * @param array $user User to send
     * @param array $message Message
     * @param array $client Sender
     * @return string
     * @author Romain GALLIEN <romaingallien.rg@gmail.com>
     */
    protected function send_message($user = array(), $message = array(), $client = array())
    {
        // Send the message
        $user->send($message);

        // We have to check if event callback must be called
        if (!empty($this->CI->ratchet_client->callback['event'])) {

            // At this moment we have to check if we have authent callback defined
            call_user_func_array($this->CI->ratchet_client->callback['event'], array((valid_json($message) ? json_decode($message) : $message)));

            // Output
            if ($this->CI->ratchet_client->debug) {
                output('info', 'Callback event "' . $this->CI->ratchet_client->callback['event'][1] . '" called');
            }
        }

        // Output
        if ($this->CI->ratchet_client->debug) {
            output('info', 'Client (' . $client->resourceId . ') send \'' . $message . '\' to (' . $user->resourceId . ')');
        }
    }
}

1 个答案:

答案 0 :(得分:0)

这是一个非常愚蠢的错误,因为我正在检查 if (empty($auth) or !is_integer($auth)) 我的 is_integer($auth) 失败了,所以我在 if 语句之前添加了 $auth=(int)$auth; 并且问题解决了...