【发布时间】: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() {
//
}
}
?>
【问题讨论】: