1.优化ws返回参数不包含敏感字段user_id等
This commit is contained in:
@@ -66,10 +66,13 @@ final class GameWebSocketDispatcher
|
||||
$payloadUserId = $parsed === false ? 0 : (int) $parsed;
|
||||
}
|
||||
|
||||
$rawData = is_array($event['data'] ?? null) ? $event['data'] : [];
|
||||
$clientData = GameWebSocketPayloadHelper::sanitizeOutboundData($rawData);
|
||||
|
||||
$frame = json_encode([
|
||||
'event' => $event['event'] ?? $topic,
|
||||
'topic' => $topic,
|
||||
'data' => $event['data'] ?? [],
|
||||
'data' => $clientData,
|
||||
'server_time' => $event['server_time'] ?? time(),
|
||||
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
if (!is_string($frame) || $frame === '') {
|
||||
@@ -128,9 +131,20 @@ final class GameWebSocketDispatcher
|
||||
*/
|
||||
public static function sendDirect(TcpConnection $connection, string $event, array $data, string $tag = ''): void
|
||||
{
|
||||
$controlEvents = ['ws.connected', 'ws.subscribed', 'ws.error', 'pong'];
|
||||
$payload = $data;
|
||||
if (!in_array($event, $controlEvents, true)) {
|
||||
if (isset($payload['data']) && is_array($payload['data'])) {
|
||||
$payload['data'] = GameWebSocketPayloadHelper::sanitizeOutboundData($payload['data']);
|
||||
}
|
||||
}
|
||||
if ($event === 'ws.connected') {
|
||||
unset($payload['user_id']);
|
||||
}
|
||||
|
||||
$frame = json_encode(array_merge([
|
||||
'event' => $event,
|
||||
], $data), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
], $payload), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
if (!is_string($frame) || $frame === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,22 @@ final class GameWebSocketPayloadHelper
|
||||
'bet.accepted',
|
||||
];
|
||||
|
||||
/**
|
||||
* 下发给客户端前从 data 中移除的字段(服务端入队/路由仍保留完整载荷)。
|
||||
*
|
||||
* @var list<string>
|
||||
*/
|
||||
public const OUTBOUND_STRIP_KEYS = [
|
||||
'user_id',
|
||||
'uuid',
|
||||
'phone',
|
||||
'balance_before',
|
||||
'channel_id',
|
||||
'review_admin_id',
|
||||
'operator_admin_id',
|
||||
'idempotency_key',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return array{user_id: int, current_streak: int, streak_level: int, odds_factor: int, is_jackpot: bool}
|
||||
*/
|
||||
@@ -53,6 +69,53 @@ final class GameWebSocketPayloadHelper
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 出站 WebSocket 帧 data 脱敏:移除 user_id 等(连接已绑定用户,无需在载荷中重复暴露)。
|
||||
*
|
||||
* @param array<string, mixed> $data
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public static function sanitizeOutboundData(array $data): array
|
||||
{
|
||||
return self::stripSensitiveKeysRecursive($data, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $data
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private static function stripSensitiveKeysRecursive(array $data, int $depth): array
|
||||
{
|
||||
if ($depth > 8) {
|
||||
return $data;
|
||||
}
|
||||
$out = [];
|
||||
foreach ($data as $key => $value) {
|
||||
if (!is_string($key)) {
|
||||
continue;
|
||||
}
|
||||
if (in_array($key, self::OUTBOUND_STRIP_KEYS, true)) {
|
||||
continue;
|
||||
}
|
||||
if (is_array($value)) {
|
||||
$isList = array_is_list($value);
|
||||
$child = [];
|
||||
foreach ($value as $k => $item) {
|
||||
if (is_array($item)) {
|
||||
$child[$k] = self::stripSensitiveKeysRecursive($item, $depth + 1);
|
||||
} else {
|
||||
$child[$k] = $item;
|
||||
}
|
||||
}
|
||||
$out[$key] = $isList ? array_values($child) : $child;
|
||||
continue;
|
||||
}
|
||||
$out[$key] = $value;
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $payload
|
||||
* @return array<string, mixed>
|
||||
|
||||
@@ -126,9 +126,7 @@ class GameWebSocketServer
|
||||
|
||||
GameWebSocketDispatcher::sendDirect($connection, 'ws.connected', [
|
||||
'message' => 'WebSocket connected',
|
||||
'connection_id' => $connection->id,
|
||||
'mode' => $auth['mode'],
|
||||
'user_id' => $auth['user_id'],
|
||||
'server_time' => time(),
|
||||
'heartbeat_interval' => 30,
|
||||
'idle_timeout' => self::HEARTBEAT_IDLE_SECONDS,
|
||||
@@ -286,7 +284,7 @@ class GameWebSocketServer
|
||||
$payload = json_encode([
|
||||
'event' => 'admin.live.snapshot',
|
||||
'topic' => 'admin.live.snapshot',
|
||||
'data' => $snapshot,
|
||||
'data' => GameWebSocketPayloadHelper::sanitizeOutboundData($snapshot),
|
||||
'server_time' => time(),
|
||||
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
if (!is_string($payload) || $payload === '') {
|
||||
|
||||
Reference in New Issue
Block a user