任务说明书 133 — voice_asr.py POST /asr auth 加固(P0 安全巡检)
任务编号: 133
版本: v1.0
创建日期: 2026-08-03
完成日期: 2026-08-03
负责人: Duckula
优先级: 🔴 P0(安全巡检发现,连续 2 次标记)
类型: 安全加固(后端 + 测试 + 文档同步)
状态: ✅ 已完成(含 E2E 验证)
📋 任务概览
| 项目 |
内容 |
| 任务名 |
voice_asr.py POST /asr auth 加固 |
| 触发 |
P0 安全巡检:src/backend/app/api/voice_asr.py POST /asr 上传端点无 auth 依赖,连续 2 次标记 |
| 风险 |
🔴 高 — 任意用户可上传文件消耗存储或上传恶意文件;H5 端 PC/Mac 企微用户为真实生产调用方,未鉴权直接对外暴露 |
| 目标 |
加 Depends(get_current_user) + 大小上限 + Content-Type 白名单 + 审计日志 |
| 关联技术方案 |
docs/02-技术文档/技术架构/技术方案-REQ-AI-003-语音转文字-v1.1.md §10 |
| 关联源码 |
src/backend/app/api/voice_asr.py + src/backend/tests/test_voice_asr.py |
| 估时 |
实际 ~1.5 h(含 403/404 部署排查 + 文档同步 + 部署) |
🎯 任务背景
现状(巡检发现)
- ✅ 已上线:
src/backend/app/api/voice_asr.py 提供 POST /voice/asr 百度 ASR 端点
- 🔴 无 auth 依赖:任意已登录用户均可调用,恶意用户可消耗百度 ASR 配额
- 🔴 无大小限制:可上传任意大小文件导致 worker 阻塞(
--workers 1)
- 🔴 无 Content-Type 校验:恶意 payload 可直达百度 ASR
- 🟡 无审计日志:无法追溯是谁在什么时间调了几次
调用方(修复前未识别清楚)
- ❌ 曾被误判为"孤儿接口"——实际 H5 端 PC/Mac 企微用户每日调用此端点
- ✅ H5 端采用"双策略自动切换"(手机企微 JS-SDK / PC/Mac 端企微 百度 ASR)
- ✅ 详见技术方案 v1.1 §10.1
📥 输入项来源
| # |
输入项 |
路径 |
用途 |
| 1 |
关联技术方案 |
docs/02-技术文档/技术架构/技术方案-REQ-AI-003-语音转文字-v1.0.md → v1.1 §10 |
修复依据 |
| 2 |
关联源码(修复前) |
src/backend/app/api/voice_asr.py |
当前实现 |
| 3 |
H5 端调用链 |
src/frontend-h5/src/components/chat/InputBar.vue:246-265 + src/frontend-h5/src/composables/useAudioRecorder.ts + src/frontend-h5/src/api/voice.ts |
调用方验证 |
| 4 |
apiClient 拦截器 |
src/frontend-h5/src/api/index.ts:38-44 |
加 auth 兼容性确认 |
| 5 |
统一认证依赖 |
src/backend/app/dependencies/__init__.py (get_current_user) |
复用现有依赖 |
📤 输出成果要求
代码改动(必须)
| # |
文件 |
改动 |
| 1 |
src/backend/app/api/voice_asr.py |
加 Depends(get_current_user) 注入 current_user: UserInfo |
| 2 |
src/backend/app/api/voice_asr.py |
加 MAX_AUDIO_SIZE = 10 * 1024 * 1024 常量 + 大小校验 |
| 3 |
src/backend/app/api/voice_asr.py |
加 ALLOWED_AUDIO_CONTENT_TYPES 白名单常量 + Content-Type 校验 |
| 4 |
src/backend/app/api/voice_asr.py |
所有日志加 current_user.employee_id 审计字段 |
测试改动(必须)
| # |
文件 |
改动 |
| 5 |
src/backend/tests/test_voice_asr.py |
加 from app.dependencies import UserInfo + _make_mock_user() helper |
| 6 |
src/backend/tests/test_voice_asr.py |
批量替换 13 处 transcribe_audio(mock_audio) → transcribe_audio(mock_audio, _make_mock_user()) |
| 7 |
src/backend/tests/test_voice_asr.py |
_make_mock_audio() 加 content_type="audio/pcm" 兼容白名单 |
文档同步(必须,避免下次同类误判)
| # |
文件 |
改动 |
| 8 |
docs/02-技术文档/技术架构/技术方案-REQ-AI-003-语音转文字-v1.0.md |
v1.0 → v1.1 + 头部变更记录 + §10 增量更新(7 个子节) |
| 9 |
docs/05-运营文档/02-用户手册/手册-坐席端.md |
v1.0 → v1.1 + §5.4 修正错误描述(PC 端百度 ASR → 三环境矩阵) |
| 10 |
docs/04-运维文档/运维指南/配置清单与环境变量.md |
BAIDU_ASR_* 加调用方说明 + 加 auth 验证命令 |
| 11 |
docs/00-产品开发流程与文档管理规范.md |
v1.12 → v1.13 + 新增 §16 增量更新章节治理(6 个子节) |
🔧 验证方式
1. 单元测试(开发环境)
2. 部署前静态检查
3. 部署后服务端验证(容器内)
4. 端到端验证(用户实测)
- ✅ 电脑端(PC Chrome/Edge 坐席工作台)→ Web Speech API 正常
- ✅ 手机端(企微 WebView H5)→ 企微 JS-SDK 正常
- ✅ 员工端(H5 PC/Mac 企微 WebView)→ 前端录音 + /voice/asr + 百度 ASR 正常
- ✅ 坐席端(PC Chrome/Edge)→ Web Speech API 正常
✅ 完成标准
| # |
标准 |
状态 |
| 1 |
voice_asr.py 加 Depends(get_current_user) |
✅ |
| 2 |
MAX_AUDIO_SIZE = 10MB 校验生效 |
✅ |
| 3 |
ALLOWED_AUDIO_CONTENT_TYPES 白名单校验生效 |
✅ |
| 4 |
日志含 current_user.employee_id |
✅ |
| 5 |
测试 16/16 PASS |
✅ |
| 6 |
技术方案 v1.0 → v1.1(+§10) |
✅ |
| 7 |
运营手册 §5.4 修正 |
✅ |
| 8 |
配置清单 BAIDU_ASR_* 调用方说明 |
✅ |
| 9 |
规范 v1.12 → v1.13(+§16) |
✅ |
| 10 |
jumpserver-V2 部署 + 健康检查 |
✅ |
| 11 |
四端用户实测 E2E 通过 |
✅ |
全部完成 ✅
📊 关键指标
| 指标 |
值 |
| 代码改动文件 |
2(voice_asr.py + test_voice_asr.py) |
| 文档同步文件 |
4(技术方案 + 运营手册 + 配置清单 + 规范) |
| 测试用例 |
16(全部 PASS) |
| 部署耗时 |
~12 min(含 403/404 排查) |
| E2E 验证 |
4 端全部通过 |
| 经验沉淀 MEMORY |
4 条新铁律 |
| 规范新增章节 |
§16(6 个子节) |
🔗 关联文档
- 技术方案:
docs/02-技术文档/技术架构/技术方案-REQ-AI-003-语音转文字-v1.1.md(v1.0 已升级,§10 增量更新)
- 规范 v1.13:
docs/00-产品开发流程与文档管理规范.md §16(增量更新治理)
- daily log:
docs/.workbuddy/memory/2026-08-03.md
- 项目 MEMORY:
docs/.workbuddy/memory/MEMORY.md(新增 4 条铁律)
⚠️ 后续治理(不影响本次闭环)
- 编号 REQ-AI-003 冲突:技术方案编号与产品 PRD-REQ-AI-003-多模态视觉理解 同号冲突 → 下次 AI 模块迭代时统一治理为 REQ-AI-009
- HTTPBearer 403 vs 401 统一:是否改为 401 取决于项目偏好;建议作为独立改进项
- 生产环境 E2E 录屏:建议录一段语音识别全流程作为回归测试素材
文档结束