乐闻世界logo
搜索文章和话题

如何保护 WebSocket 连接的安全性?

2月18日 21:30

在生产环境中保护 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):

javascript
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 攻击:

javascript
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. 输入验证和消息过滤

验证所有传入消息:

javascript
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. 连接超时管理

设置合理的超时时间:

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. 日志和监控

记录安全相关事件:

javascript
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 头部
  • 实现速率限制
  • 验证所有输入消息
  • 设置连接超时
  • 记录安全事件日志
  • 定期更新依赖库
  • 进行安全审计和渗透测试
标签:WebSocket