在生产环境中保护 WebSocket 连接需要多层次的安全措施。以下是关键的安全实践:
1. 使用 WSS(WebSocket Secure)
强制使用加密连接:
javascript// 始终使用 wss:// 而不是 ws:// const ws = new WebSocket('wss://example.com/socket'); // 验证证书 const ws = new WebSocket('wss://example.com/socket', { rejectUnauthorized: true // 拒绝无效证书 });
WSS 的优势:
- 数据传输加密(TLS/SSL)
- 防止中间人攻击
- 保护敏感信息不被窃听
2. 身份验证和授权
连接时验证
javascript// 在握手时传递认证令牌 const ws = new WebSocket(`wss://example.com/socket?token=${authToken}`); // 或在连接建立后发送认证消息 ws.onopen = () => { ws.send(JSON.stringify({ type: 'auth', token: authToken })); };
服务器端验证
javascript// 验证 JWT 令牌 function validateConnection(token) { try { const decoded = jwt.verify(token, SECRET_KEY); return decoded.userId; } catch (error) { return null; } } // 握手时验证 wss.on('connection', (ws, req) => { const token = req.url.split('token=')[1]; const userId = validateConnection(token); if (!userId) { ws.close(1008, 'Unauthorized'); return; } // 认证成功,继续处理 });
3. Origin 头部验证
防止跨站 WebSocket 劫持(CSWSH):
javascriptwss.on('connection', (ws, req) => { const origin = req.headers.origin; const allowedOrigins = ['https://yourdomain.com', 'https://app.yourdomain.com']; if (!allowedOrigins.includes(origin)) { ws.close(1003, 'Unsupported Data'); return; } // 允许连接 });
4. 速率限制和节流
防止消息洪泛和 DoS 攻击:
javascriptconst rateLimiter = new Map(); function checkRateLimit(userId) { const now = Date.now(); const userLimit = rateLimiter.get(userId); if (!userLimit) { rateLimiter.set(userId, { count: 1, resetTime: now + 60000 }); return true; } if (now > userLimit.resetTime) { rateLimiter.set(userId, { count: 1, resetTime: now + 60000 }); return true; } if (userLimit.count >= 100) { // 每分钟最多100条消息 return false; } userLimit.count++; return true; } wss.on('connection', (ws, req) => { ws.on('message', (message) => { if (!checkRateLimit(userId)) { ws.send(JSON.stringify({ type: 'error', message: 'Rate limit exceeded' })); return; } // 处理消息 }); });
5. 输入验证和消息过滤
验证所有传入消息:
javascriptfunction validateMessage(message) { const data = JSON.parse(message); // 验证消息结构 if (!data.type || typeof data.type !== 'string') { return false; } // 验证消息类型 const allowedTypes = ['chat', 'ping', 'auth']; if (!allowedTypes.includes(data.type)) { return false; } // 验证数据大小 if (JSON.stringify(data).length > 10240) { // 10KB 限制 return false; } // 验证内容(防止 XSS) if (data.content && /<script|javascript:|onerror=/i.test(data.content)) { return false; } return true; } ws.on('message', (message) => { if (!validateMessage(message)) { ws.close(1007, 'Invalid frame payload data'); return; } // 处理有效消息 });
6. 连接超时管理
设置合理的超时时间:
javascript// 服务器端超时设置 const server = http.createServer(); const wss = new WebSocket.Server({ server, clientTracking: true, perMessageDeflate: false }); // 设置 ping/pong 超时 wss.on('connection', (ws) => { ws.isAlive = true; ws.on('pong', () => { ws.isAlive = true; }); }); // 定期检查连接状态 const interval = setInterval(() => { wss.clients.forEach((ws) => { if (ws.isAlive === false) { return ws.terminate(); } ws.isAlive = false; ws.ping(); }); }, 30000); wss.on('close', () => { clearInterval(interval); });
7. 日志和监控
记录安全相关事件:
javascriptconst securityLogger = { logConnection: (userId, ip, userAgent) => { console.log(`[SECURITY] Connection from ${ip} - User: ${userId} - UA: ${userAgent}`); }, logUnauthorized: (ip, reason) => { console.warn(`[SECURITY] Unauthorized connection attempt from ${ip} - Reason: ${reason}`); }, logSuspiciousActivity: (userId, activity) => { console.error(`[SECURITY] Suspicious activity from user ${userId}: ${activity}`); } };
8. 网络层安全
防火墙和负载均衡器配置:
- 限制连接来源 IP
- 设置最大连接数
- 启用 DDoS 防护
- 配置 Web 应用防火墙(WAF)
安全检查清单
- 使用 WSS 加密连接
- 实施身份验证机制
- 验证 Origin 头部
- 实现速率限制
- 验证所有输入消息
- 设置连接超时
- 记录安全事件日志
- 定期更新依赖库
- 进行安全审计和渗透测试