bea288e414
== 已部署上线 (9项) == - 代办事项真实数据源集成 (企微审批API 8bug修复链) - H5/坐席端 Logo样式统一+绿色背景 - 视频引导页修复 (localStorage key v2) - 坐席端 v9 Vue版本修复 (ElMessage._context) - 截图按钮 v10 修复 (getDisplayMedia user gesture) - 扫码样式恢复+H5扫码登录跳转修复 - H5截图快捷键提示 == 代码完成待部署 (3项) == - 知识迭代3Bug修复 (#8 POST端点/#7 MERGE幂等/#6 过期检查) - 会议室预定-小鱼易联终端 (40文件, 40/40测试通过) - IT资产升级审批推送 (asset_service.py) == 需求文档 (2项) == - 坐席端AI辅助消息框-PRD (4项新功能确认) - 坐席端布局优化建议 v2.0 (7天计划) == 新增文档 == - 日报-2026-07-11.md - 知识迭代Bug修复报告-20260711.md - 会议室预定-部署指南.md - CHANGELOG.md 更新 == 测试 == - test_todo_integration.py: 40/40 - test_meetingroom.py: 40/40 - test_bugfix_ki_suggestions.py: 21/21
3.2 KiB
3.2 KiB
头像显示修复报告 — 2026-07-10
问题摘要
坐席端(https://itsupport.servyou.com.cn/itagent/workspace)员工头像仍不显示,浏览器控制台报三类错误:
- COEP 阻断 —
ERR_BLOCKED_BY_RESPONSE.NotSameOriginAfterDefaultedToSameOriginByCoep - Mixed Content — HTTPS 页面不允许加载 HTTP 资源
- CSP 限制 —
img-src白名单不含wework.qpic.cn
根因分析
三层安全策略叠加导致企微头像域名 wework.qpic.cn 被完全拦截:
| 安全策略 | nginx 配置 | 拦截表现 |
|---|---|---|
| COEP | require-corp |
跨域图片无 CORS 头被拦截 |
| Mixed Content | — | HTTP 图片在 HTTPS 页面被拦截 |
| CSP | img-src 'self' data: https://res.wx.qq.com |
wework.qpic.cn 不在白名单 |
修复方案:后端头像代理
不修改 nginx 安全头(保持安全级别不变),通过后端代理绕过所有三层限制:
前端 img.src = "/api/avatar/proxy?url=<encoded_avatar_url>"
|
v
后端 httpx.AsyncClient → wework.qpic.cn
|
v
返回图片字节流 (同域, HTTPS, 不受 CSP 限制)
修改文件
| 文件 | 操作 | 修改内容 |
|---|---|---|
backend/app/services/avatar_service.py |
修改 | clean_avatar_url 增加 HTTP→HTTPS 转换;新增 wrap_avatar_url 代理 URL 包装函数 |
backend/app/services/session_service.py |
修改 | 3个头像返回路径统一应用 wrap_avatar_url |
backend/app/api/avatar.py |
新建 | 头像代理端点 /api/avatar/proxy,SSRF 白名单校验 wework.qpic.cn,httpx.AsyncClient 异步获取,返回 Response(content=..., media_type="image/jpeg") |
backend/app/api/router.py |
修改 | 注册 avatar_router 路由,前缀 /api/avatar/proxy |
验证结果
1. API 层(curl)
| 测试项 | 结果 |
|---|---|
| 代理 HTTPS 头像 URL | ✅ HTTP 200, image/jpeg, 42KB |
| 代理 HTTP 头像 URL(自动转 HTTPS) | ✅ HTTP 200, image/jpeg, 65KB |
| 无效 URL(非企微域名) | ✅ 403 拒绝 |
2. 浏览器验证(agent-browser)
- ✅ 坐席工作台正常加载,无重定向到登录页
- ✅ 3个头像全部通过代理加载:
GET /api/avatar/proxy?url=... (Image) 200× 3
- ✅ 控制台零错误:无 COEP、无 Mixed Content、无 CSP 报错
- ✅ 网络请求零 4xx/5xx
- ✅ 头像在左侧会话列表和顶部导航栏均正常显示
3. 截图证据
见 screenshot-1783683005062.png — 坐席工作台界面,头像正常显示在左侧列表和顶部用户信息区域。
部署摘要
- 上传 4 个修改文件 →
/tmp/ cp到/opt/wecom-it-desk/app/对应路径docker compose restart backend- 清除 Redis 头像缓存
employee:avatar:*(3 个 key) - 代理端点
/api/avatar/proxy即时生效
关于"获取坐席列表失败"
本次浏览器验证中未复现该错误。该错误与头像代理无关,如持续出现需检查后端日志中 /api/agents 的具体报错(可能为认证或数据库问题)。