feat: 修复 WebSocket 越权与 AI 流 SSRF

This commit is contained in:
weijuesen
2026-08-14 00:45:22 +08:00
parent 1a29def480
commit 839ba91354
17 changed files with 614 additions and 136 deletions
+19 -5
View File
@@ -1,17 +1,19 @@
import { WS_BASE_URL } from '@env';
import { get } from '../api/client';
export type WSMessageHandler = (data: any) => void;
class WebSocketManager {
private ws: WebSocket | null = null;
private token: string | null = null;
private ticket: string | null = null;
private handlers: Set<WSMessageHandler> = new Set();
private reconnectTimer: ReturnType<typeof setTimeout> | null = null;
private reconnectAttempts = 0;
private maxReconnectAttempts = 10;
private isManualClose = false;
connect(token: string): void {
async connect(token: string): Promise<void> {
// Close any existing connection before creating a new one
if (this.ws) {
this.isManualClose = true;
@@ -27,14 +29,14 @@ class WebSocketManager {
this.reconnectAttempts = 0;
this.token = token;
this.isManualClose = false;
this.doConnect();
await this.refreshTicketAndConnect();
}
private doConnect(): void {
if (!this.token) return;
if (!this.token || !this.ticket) return;
const wsUrl = (WS_BASE_URL || 'ws://localhost:3000/ws').replace(/\?.*$/, '');
const url = `${wsUrl}?token=${encodeURIComponent(this.token)}`;
const url = `${wsUrl}?ticket=${encodeURIComponent(this.ticket)}`;
try {
this.ws = new WebSocket(url);
@@ -84,11 +86,23 @@ class WebSocketManager {
this.reconnectTimer = setTimeout(() => {
if (!this.isManualClose && this.token) {
this.doConnect();
this.refreshTicketAndConnect();
}
}, delay);
}
private async refreshTicketAndConnect(): Promise<void> {
if (!this.token) return;
try {
const { ticket } = await get<{ ticket: string }>('/ws/ticket');
this.ticket = ticket;
this.doConnect();
} catch (e) {
console.warn('[WS] Failed to fetch ticket:', e);
this.scheduleReconnect();
}
}
disconnect(): void {
this.isManualClose = true;
if (this.reconnectTimer) {