# 任务说明书 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. 单元测试(开发环境) ```bash cd src/backend && python -m pytest tests/test_voice_asr.py -v # 期望:16/16 PASS ``` ### 2. 部署前静态检查 ```bash python -m py_compile src/backend/app/api/voice_asr.py python -m py_compile src/backend/tests/test_voice_asr.py ``` ### 3. 部署后服务端验证(容器内) ```bash # 无 Token → 应拒绝(HTTP 403 FastAPI HTTPBearer 默认 / 401 get_current_user) docker exec wecom_it_backend curl -X POST http://127.0.0.1:8000/voice/asr \ -H "Content-Type: application/json" -d '{}' # 期望:403 + {"detail":"Not authenticated"} # 带错误 Token → 应返回 401 docker exec wecom_it_backend curl -X POST http://127.0.0.1:8000/voice/asr \ -H "Authorization: Bearer fake-token" \ -H "Content-Type: application/octet-stream" --data-binary "test" # 期望:401 ``` ### 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 条铁律) --- ## ⚠️ 后续治理(不影响本次闭环) 1. **编号 REQ-AI-003 冲突**:技术方案编号与产品 PRD-REQ-AI-003-多模态视觉理解 同号冲突 → 下次 AI 模块迭代时统一治理为 REQ-AI-009 2. **HTTPBearer 403 vs 401 统一**:是否改为 401 取决于项目偏好;建议作为独立改进项 3. **生产环境 E2E 录屏**:建议录一段语音识别全流程作为回归测试素材 --- *文档结束*