feat: 修复 WebSocket 越权与 AI 流 SSRF
This commit is contained in:
@@ -890,3 +890,34 @@ MVP 沿用 IoTDB(现状);TDengine 作为生产规模化候选(先基准
|
||||
|
||||
- 本任务前分支提交为 `440cf80`;回滚可还原 Task 4 提交;
|
||||
- 若已部署流代理版本,回滚需恢复旧二进制并重启,无需数据库变更;播放地址需由客户端重新请求。
|
||||
|
||||
---
|
||||
|
||||
## 2026-08-14 整改 Task 5:修复 WebSocket 越权与 AI 流 SSRF
|
||||
|
||||
### 做了什么
|
||||
|
||||
- WebSocket 改为一次性 ticket 连接:`GET /api/v1/ws/ticket` 签发 60 秒单次 ticket,`/ws` 不再接受 JWT query,客户端统一使用 ticket;
|
||||
- 新增 `DeviceAuthorizer` / `DBDeviceAuthorizer`,`subscribe.device` 必须校验用户 `device:read` 权限;无权订阅返回 `subscribe.denied`;
|
||||
- WebSocket 增加 Origin 白名单,`WS_ALLOWED_ORIGINS` 可配置;
|
||||
- 移除普通连接的 `telemetry.all`、全局 `alarm`、全局 `device.status` 广播,只推送给已授权订阅的设备房间;
|
||||
- APP/小程序 WS 客户端先请求 ticket 再连接,避免长期 JWT 进入 URL;
|
||||
- AI 服务新增 `POST /internal/stream-tasks`:要求 `X-Internal-Key`、`taskId`、`streamRef`,限制拉流 host 白名单、并发 worker 数和最大帧数;旧 `/stream-detect` 任意 URL 入口改为 410。
|
||||
|
||||
### 设计思路与决策依据
|
||||
|
||||
- WebSocket 播放/订阅场景不适合把长期 JWT 放进 URL;采用服务端签发的一次性 ticket 降低代理日志泄露和重放风险;
|
||||
- 当前没有用户级资源 ACL,设备订阅先用 RBAC `device:read` 做对象授权;组织/房间级 ACL 留待后续任务;
|
||||
- AI 流任务改为内部服务接口和受限 worker,避免公网客户端直接传任意 URL,也避免在 FastAPI 事件循环中阻塞式 `VideoCapture.read()`。
|
||||
|
||||
### 验证结果
|
||||
|
||||
- `scripts/verify.ps1` 最终 exit 0:Go test/vet/build、Web、小程序、APP、AI pytest 11/11 均通过;
|
||||
- 新增 Go WS 测试覆盖非法 Origin、ticket 单次/过期、JWT query 拒绝、无权设备订阅、全局广播不泄露;
|
||||
- 新增 AI 测试覆盖内部 key 校验、任务创建、metadata/公网地址拒绝和旧接口禁用;
|
||||
- 未部署开发服务器,未做真实 WS 推送和摄像头拉流联调。
|
||||
|
||||
### 回滚点
|
||||
|
||||
- 本任务前分支提交为 `1a29def`;回滚可还原 Task 5 提交;
|
||||
- WS/AI 改动无数据库 schema 变更;若已部署,恢复旧二进制并重启即可,但需同步回滚客户端 WS 连接方式。
|
||||
|
||||
Reference in New Issue
Block a user