如何Implement 安全 WebSockets
Establish 和 maintain 安全 WebSocket (WSS) connections 具有 proper 认证, 源 validation, 和消息完整性.
问题
WebSocket connections 能够是 hijacked, lack 认证, 或接受 messages 从未授权 origins. 你需要implement 安全 WebSockets (wss://) 具有 proper 认证, 源 checking, 和保护针对常见 attacks.
前置条件
- Understanding 的 WebSocket 协议 (RFC 6455)
- 熟悉TLS 和 wss:// scheme
- Knowledge 的 HTTP 认证和 CORS
步骤
-
1. Establish WSS with TLS and authentication
Always use wss:// (WebSocket Secure over TLS), never ws:// in production. Perform authentication during the WebSocket handshake: pass a token in the initial HTTP upgrade request (via Authorization header, query parameter, or Sec-WebSocket-Protocol subprotocol). Validate the token before accepting the upgrade. The server must reject the upgrade (HTTP 401/403) if authentication fails. Use the WebSocket frame encoder/decoder to understand the protocol.
输入GET /ws HTTP/1.1 | Upgrade: websocket | Authorization: Bearer <token>输出HTTP 101 Switching Protocols (if auth valid) | HTTP 401 (if auth fails) -
2. Validate the Origin header
Check the Origin header on the upgrade request against an allow-list of trusted origins. This prevents Cross-Site WebSocket Hijacking (CSWSH) where a malicious website opens a WebSocket to your server using the victim's browser credentials. Reject requests with missing or untrusted origins with HTTP 403. Do not use CORS for WebSockets — Origin checking is the WebSocket-specific mechanism. Use the URL parser to validate origin format.
输入Origin: https://trusted.example.com输出origin_check: pass | (Origin: https://evil.com -> reject 403) -
3. Implement message validation and rate limiting
Validate every incoming message against a schema (JSON Schema, protobuf) before processing. Reject malformed, oversized, or unexpected message types. Enforce a maximum message size (e.g., 1MB) and rate limit per connection (messages per second). Use ping/pong frames for keepalive and to detect dead connections. Set reasonable timeouts for idle connections. Use the JSON validator and WebSocket frame decoder for message inspection.
输入message: { type: chat, text: hello }输出valid: true | processed | (oversized: reject 1009 Message Too Big) -
4. Secure the connection lifecycle
Implement proper connection cleanup: close connections on authentication expiry, set idle timeouts, and handle close codes (1000 normal, 1001 going away, 1008 policy violation, 1011 internal error). Re-authenticate on reconnection. Never send sensitive data in broadcast messages. Log connection events for audit. For multi-server deployments, use a shared session store and authenticate on each server, not just the one that received the upgrade.
输入token expired mid-session输出close: 1008 Policy Violation | reason: auth expired
预期结果
安全 WebSocket connections 具有 TLS, per-连接认证, 源 validation, 消息模式 enforcement, 和速率 limiting.
常见错误
- Using ws:// instead of wss:// in production
- Always use wss:// (TLS). ws:// sends all data including tokens in plaintext, vulnerable to interception and modification.
- Not validating the Origin header
- Without Origin validation, any website can open a WebSocket to your server using the user's browser session. Always check Origin against an allow-list.
- Authenticating only at connection, not per-message
- For long-lived connections, the initial token may expire. Re-validate periodically or on sensitive operations. Close connections with expired credentials.
排障指引
- If connections drop frequently, check proxy/load balancer WebSocket support and timeout settings (e.g., Nginx proxy_read_timeout).
- If the Origin check blocks legitimate connections, ensure your CDN/proxy forwards the Origin header correctly.
- For large messages, consider chunking or using a separate file upload channel rather than sending large payloads over WebSocket.
安全限制
- WebSocket connections are stateful and long-lived — a compromised token remains valid until the connection closes or the token is re-validated.
- All authentication and message validation happen server-side; the client must not be trusted to enforce security policies.
- Broadcast messages can leak data to unauthorized clients if not filtered per-recipient.