长连接带来的新问题
WebSocket 在握手阶段借用一次 HTTP 请求完成升级,之后变为长连接双向通道,不再有请求与响应的语义。常见问题因此集中在几处:握手阶段没做身份校验、只校验页面来源不校验身份、消息层面缺少权限与频率限制,以及连接建立后权限变更无法即时生效。
基本信息
| 协议 | ws:// 明文、wss:// 加密,生产应使用 wss |
|---|---|
| 握手 | 一次 HTTP Upgrade 请求,之后转为长连接 |
| 校验点 | 握手鉴权、Origin 校验、消息级授权、频率与大小限制 |
| 代理要求 | Nginx 需 proxy_http_version 1.1 与 Upgrade 头透传 |
| 审计要求 | 记录消息类型、来源与异常模式 |
典型使用场景
- 实时消息推送:站内通知、聊天与协同编辑
- 行情与监控大屏:持续订阅数据流
- 任务进度回显:长耗时任务的状态推送
- 运维控制通道:设备与平台的指令下发(风险最高)
- 内嵌于单页应用:前端在页面加载后建立连接
安全检查清单
安全检查清单
握手:校验 Cookie 或令牌,未认证直接拒绝升级请求
来源:浏览器场景校验 Origin 头并使用白名单
消息:每条消息重新校验权限,不只信任连接建立时的身份
限流:限制消息速率与单条大小,防止资源耗尽
长度:限制连接数与单连接并发订阅数
审计:记录消息类型、来源地址与异常模式Nginx 反代配置
Nginx 反代配置
location /ws/ {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1; # WebSocket 要求 1.1
proxy_set_header Upgrade $http_upgrade; # 透传升级请求
proxy_set_header Connection "upgrade";
proxy_read_timeout 300s; # 空闲超时,避免连接被静默断开
proxy_set_header X-Real-IP $remote_addr;
}风险与防护
| 风险 | 成因 | 防护 |
|---|---|---|
| 未授权连接 | 握手不校验身份 | 握手阶段强制认证 |
| 跨站连接 | 只信任页面来源 | 校验 Origin 白名单 |
| 消息越权 | 按连接身份放行全部消息 | 每条消息重新校验权限 |
| 资源耗尽 | 无速率与大小限制 | 限制速率、大小与连接数 |
| 权限滞后 | 连接存续期间权限变更未生效 | 按需断开会话或缩短令牌有效期 |
wss://(TLS 加密)是标配:明文 ws:// 会让会话标识与业务数据在链路上暴露,与使用明文口令登录的风险同级。
反向代理层的空闲超时与业务心跳要匹配:代理超时短于心跳间隔时,连接会被周期性断开,表现为用户侧频繁重连而日志里看不出明显错误。