【问题标题】:How can I get cookies from socket message (PHP)?如何从套接字消息(PHP)中获取 cookie?
【发布时间】:2021-01-06 20:11:32
【问题描述】:

我有一个用 PHP 编写的套接字聊天应用程序脚本。我想对用户进行身份验证,但我无法仅在握手时从请求标头中获取 cookie。这是我下面的脚本。当客户端发送消息时,如何每次获取 cookie? getallheaders 函数不起作用,因为它不包含 cookie。 socket_recv 函数只给了我请求的主体。 SocketController 在这种情况下并不重要,它只做错误检查,并且有一些字段声明。

<?php namespace Models\Messages;
use Controllers\Messages\SocketController;
use Models\Logs\ErrorLog;
use PDO;

class Socket extends SocketController {

    public function SocketHandler() {

        $this->clientSocketArray = [$this->socketResource];

        while (true) {
            $newSocketArray = $this->clientSocketArray;
            socket_select($newSocketArray, $null, $null, 0, 10);
            
            if (in_array($this->socketResource, $newSocketArray)) {
                $newSocket = socket_accept($this->socketResource);
                $this->clientSocketArray[] = $newSocket;
                $header = socket_read($newSocket, 1024);
                $this->DoHandshake($header, $newSocket, self::HOST, self::PORT);
                
                socket_getpeername($newSocket, $client_ip_address);
                $connectionACK = $this->NewConnectionACK($client_ip_address);
                
                $this->Send($connectionACK);
                
                $newSocketIndex = array_search($this->socketResource, $newSocketArray);
                unset($newSocketArray[$newSocketIndex]);
            }
            
            foreach ($newSocketArray as $newSocketArrayResource) {
                //$headers = apache_request_headers();
                $headers = getallheaders();
                file_put_contents("headers.txt", json_encode($headers), FILE_APPEND);

/*//!!!this is the message sender part!!!, I'd like to get the cookies here*/

                while(socket_recv($newSocketArrayResource, $socketData, 1024, 0) >= 1) {

                    $socketMessage = $this->Unseal($socketData);
                    $messageObj = json_decode($socketMessage, 1);

                    $senderID = isset($messageObj["senderID"]) ? (int)$messageObj["senderID"] : 0;
                    $receiverID = isset($messageObj["receiverID"]) ? (int)$messageObj["receiverID"] : 0;
                    $messageType = isset($messageObj["messageType"]) ? (int)$messageObj["messageType"] : 1;
                    $message = isset($messageObj["message"]) ? $messageObj["message"] : "nincs üzenet";
                    
                    $chat_box_message = $this->CreateChatBoxMessage(
                        $senderID, $receiverID, $messageType, $message
                    );

                    $this->Send($chat_box_message);
                    break 2;
                }
                
                $socketData = @socket_read($newSocketArrayResource, 1024, PHP_NORMAL_READ);
                if ($socketData === false) {
                    socket_getpeername($newSocketArrayResource, $client_ip_address);
                    $connectionACK = $this->ConnectionDisconnectACK($client_ip_address);
                    $this->Send($connectionACK);
                    $newSocketIndex = array_search($newSocketArrayResource, $this->clientSocketArray);
                    unset($this->clientSocketArray[$newSocketIndex]);
                }
            }
        }

        socket_close($this->socketResource);
    }

    function Send($message) {
        // global $clientSocketArray;
        $messageLength = strlen($message);

        foreach($this->clientSocketArray as $clientSocket) {
            @socket_write($clientSocket, $message, $messageLength);
        }

        return true;
    }

    function Unseal($socketData) {
        $length = ord($socketData[1]) & 127;
        if($length == 126) {
            $masks = substr($socketData, 4, 4);
            $data = substr($socketData, 8);
        }
        else if($length == 127) {
            $masks = substr($socketData, 10, 4);
            $data = substr($socketData, 14);
        }
        else {
            $masks = substr($socketData, 2, 4);
            $data = substr($socketData, 6);
        }
        $socketData = "";
        for ($i = 0; $i < strlen($data); ++$i) {
            $socketData .= $data[$i] ^ $masks[$i%4];
        }
        return $socketData;
    }

    function Seal($socketData) {
        $b1 = 0x80 | (0x1 & 0x0f);
        $length = strlen($socketData);
        
        if($length <= 125)
            $header = pack('CC', $b1, $length);
        elseif($length > 125 && $length < 65536)
            $header = pack('CCn', $b1, 126, $length);
        elseif($length >= 65536)
            $header = pack('CCNN', $b1, 127, $length);
        return $header.$socketData;
    }

    function DoHandshake($receivedHeader, $clientSocketResource, $hostName, $port) {
        $headers = array();
        $lines = preg_split("/\r\n/", $receivedHeader);
        foreach($lines as $line)
        {
            $line = chop($line);
            if(preg_match('/\A(\S+): (.*)\z/', $line, $matches))
            {
                $headers[$matches[1]] = $matches[2];
            }
        }

        $secKey = $headers['Sec-WebSocket-Key'];
        $secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
        $buffer  = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
        "Upgrade: websocket\r\n" .
        "Connection: Upgrade\r\n" .
        "WebSocket-Origin: {$hostName}/maganoktatas\r\n" .
        "WebSocket-Location: ws://$hostName:$port/maganoktatas/app/ajax/sockeg_messages.php\r\n".
        "Sec-WebSocket-Accept:$secAccept\r\n\r\n";
        socket_write($clientSocketResource, $buffer, strlen($buffer));
    }
    
    function NewConnectionACK($clientIP) {
        $message = 'New client ' . $clientIP.' joined';

        $messageArray = [
            "messageType"=>5,
            "message"=>$message
        ];

        $ACK = $this->Seal(json_encode($messageArray));
        return $ACK;
    }
    
    function ConnectionDisconnectACK($clientIP) {
        $message = 'Client ' . $clientIP.' disconnected';

        $messageArray = [
            "messageType"=>5,
            "message"=>$message
        ];
        
        $ACK = $this->Seal(json_encode($messageArray));
        return $ACK;
    }
    
    public function GetUserName(string $friendID):string {
        $stmt = $this->conn->prepare("SELECT CONCAT(LastName, ' ' , FirstName) as FullName
        FROM users WHERE UserID = ?");
        $stmt->execute([
            $friendID
        ]);

        $row = $stmt->fetch(PDO::FETCH_ASSOC);

        return isset($row["FullName"]) ? $row["FullName"] : "";
    }
    
    function CreateChatBoxMessage(int $senderID, int $receiverID, int $messageType, 
    string $message):string {

        $messageArray = [
            "messageType"=>$messageType,
            "message"=>htmlspecialchars($message),
            "receiverID"=>$receiverID,
            "senderID"=>$senderID, 
            "senderName"=>$this->GetUserName($senderID)
        ];

        $chatMessage = $this->Seal(json_encode($messageArray));
        return $chatMessage;
    }

    function __destruct() {
        //
    }
}
?>

【问题讨论】:

    标签: php sockets websocket


    【解决方案1】:

    你不能,你也不需要。 当通过 http 协议建立连接时,浏览器仅在 hanshake 期间发送 cookie。 hanshake 之后,协议从 http 变为 websocket。您的客户端通过 tcp 连接进行连接,因此当客户端发送消息时,您已经知道该消息来自谁。接受连接后,只需将您的客户端数据(id、登录名或某事)与套接字处理程序一起保存。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多