如何保护 WebSocket 连接的安全性?
在生产环境中保护 WebSocket 连接需要多层次的安全措施。以下是关键的安全实践:1. 使用 WSS(WebSocket Secure)强制使用加密连接:// 始终使用 wss:// 而不是 ws://const ws = new WebSocket('wss://example.com/socket');// 验证证书const ws = new WebSocket('wss://example.com/socket', { rejectUnauthorized: true // 拒绝无效证书});WSS 的优势:数据传输加密(TLS/SSL)防止中间人攻击保护敏感信息不被窃听2. 身份验证和授权连接时验证// 在握手时传递认证令牌const ws = new WebSocket(`wss://example.com/socket?token=${authToken}`);// 或在连接建立后发送认证消息ws.onopen = () => { ws.send(JSON.stringify({ type: 'auth', token: authToken }));};服务器端验证// 验证 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):wss.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 攻击:const 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. 输入验证和消息过滤验证所有传入消息:function 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. 连接超时管理设置合理的超时时间:// 服务器端超时设置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. 日志和监控记录安全相关事件:const 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 头部[ ] 实现速率限制[ ] 验证所有输入消息[ ] 设置连接超时[ ] 记录安全事件日志[ ] 定期更新依赖库[ ] 进行安全审计和渗透测试