Files
story/docs/tencent-captcha-integration.md
Codex Local bf1233d5df
ci / verify (push) Canceled after 0s
feat: expand companion platform, device controls, and memoir workflows
Add customer and operator login, BLE provisioning, device fleet controls, call memory, memoir generation, and refreshed family and maintenance portals. Include API contracts, migrations, firmware sources, tests, assets, and deployment documentation.
2026-10-08 10:06:44 +08:00

58 lines
8.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 登录验证码切换(2026-09-20)
## 2026-09-30:SaaS 已上线本地拼图滑块
家庭与运营网页登录已发布 `0.99.19-rc.local-slide1`,策略为 SaaS=`slide`、mini=`image`、version=4。采用固定版本 GoCaptcha v2.0.5 / assets v1.0.7 和 go-captcha-react 1.0.5,自有 API 生成图片及校验位置,无运行时第三方验证码请求。交互为弹出拼图、拖动对齐,再继续短信或密码登录。滑块挑战及一次性票据共用原 2 分钟期限,刷新、错误提交、过期和重复票据均受到服务端校验。实现和许可见 `local-slide-captcha.md` 及 `third_party/local-slide-captcha/NOTICE.md`。
发布仅更新 API/Web,应用兼容迁移 74 后再启用 slide。其他容器 ID、端口、挂载、运行环境和 Web runtime-config 摘要均核对保持一致。策略切换由真实 SSH 运维来源 service 同事务写审计,请求号 `local-slide-maintenance-6ce4f8e0-8429-4078-8053-f2ca2bb4255d`。源码以线上 release18 为基线,只发布本功能 28 个文件;同时修补扫描发现的既有 gRPC/WebSocket 两个依赖版本。
精确候选的 42 项 PostgreSQL/Redis 隔离集成、10 项 React 组件/API 测试、Linux API 和前端构建均通过,0 SKIP。govulncheck 复扫无应用可达报告。线上匿名接口核对两 Web 端返回 slide,小程序旧兼容接口仍为 image;真实 Chrome 已观察弹窗、过期提示、换图恢复与取消,未自动解题或发送短信。实测截图、冻结清单、发布回执和检查结果位于工作区外 `.local-evidence/local-slide-captcha-20260930`。真实账号登录及 OTA 完成状态需另行确认,不能由验证码显示正确推断。
## 2026-09-30:启用本地开源图片验证码
按用户要求,线上 SaaS(家庭端及运营端)已从 `tencent` 切为 `image`;小程序继续使用 `image`,策略版本从 2 递增为 3。复用项目已接入的 `github.com/dchest/captcha v1.1.0`,在自有 API 服务内生成和校验 6 位数字 PNG,不需要腾讯验证码套餐、密钥或 SDK。短信发送仍使用原短信渠道。
此次只切换现有策略,API/Web/worker 镜像及设备固件均未重新部署。授权 SSH 运维事务先锁定并核对旧版本,再修改 SaaS 模式、递增版本,并同时写入 `login.captcha.policy.update` 审计;actor 为真实运维来源 `service`,未冒用登录用户。运维审计请求号为 `local-captcha-20260930-59239939-4513-4e7c-9c11-57f7f7f4f52b`。
家庭端真实登录页已检查短信/密码两种模式均显示图片,“换一张”返回新的 PNG,2 分钟到期提示可见,刷新后恢复有效状态。答案不在 API 响应中,仍以会话和挑战 ID 绑定的 HMAC 存入 Redis,验证时原子消费;策略切换使旧挑战失效,需重新获取。现有 CSRF、登录及短信限流、新浏览器短信验证规则继续生效。
腾讯服务套餐是否到期没有确认依据;本次结论为已替换登录时使用的验证服务,不把统一的失败提示视为供应商到期证明。实测证据保存于工作区外 `.local-evidence/local-captcha-20260930`;真实账号登录和远程 OTA 仍需用户完成图片及账号验证后继续。
## 2026-09-20 的实现范围与状态(历史记录)
只实现「现有数字图形验证码 / 腾讯云验证码」,不包含自部署滑块。2026-09-20 已部署线上版本 `0.97.1-rc.tencent-captcha1`,两端仍保持 image 默认模式。上传的真实配置已通过 API/worker 非 root 加载校验,腾讯云只读查询确认对应应用存在且 SaaS 为 web、小程序为 mini。尚未发布微信小程序,也未进行人工拼图和真实云端票据校验;配置可加载、应用查询成功不等于真实验证全流程已通过。发布和回退记录见 `tencent-captcha-release-20260920.md`。
管理端入口:运行配置 → 验证码设置。SaaS(包括运营登录)与微信小程序分别选择模式,默认均为 image。配置全平台生效,需要 ops_admin;普通运营角色不可读写。修改使用版本锁并写审计;不接收、保存或展示密钥。
历史更新:2026-09-20 22:22 已发布 Web `0.98.2-rc.captcha-csp1`,修复腾讯云动态 CSS/JS/Worker 被 CSP 拦截而无法弹窗的问题,真实线上登录页可显示拼图。当时策略为 SaaS=tencent、小程序=image(version=2),该次 CSP 修复未修改策略;2026-09-30 已切回上述本地模式。详见 `tencent-captcha-csp-fix-20260920.md`。
## 配置及部署
填写 `deploy/server/tencent-captcha-template/tencent-captcha.json.example` 中的六个字符串。可编辑副本位于 `tmp/tencent-captcha.json`(已被 Git 忽略)。详细填写与插件授权步骤见该模板目录 README。
服务器文件:`/etc/data-terminal-cloud/voice-runtime/tencent-captcha.json`,root:65532、640。容器通过现有只读挂载读取 `/run/secrets/voice-runtime/tencent-captcha.json`。也支持环境变量 TENCENT_CAPTCHA_CONFIG_FILE 指定绝对路径。仅 api/worker 读取。填写 JSON 不会自动切换模式;重启服务加载配置后由管理端保存模式。
部署需先应用迁移 71,并更新 API、worker、Web 镜像。Web 镜像必须包含修改后的 `deploy/web.nginx.conf`,否则旧 CSP 会阻止腾讯云 SDK 和 iframe。后续发布以线上 0.97.0-rc.tencent-sms1 为基线,只覆盖本功能文件;本地存在其他页面样式改动,不能混入本次发布。不要替换现有服务器的短信密钥或环境文件。
小程序需授权插件 `wx1fe8d9a3cb067a75`(腾讯验证码 2.1.5),重新编译、真机验证和提交发布;旧版客户端未发布前不要切换 mini_mode。回退方式为管理员将两端改回 image;若凭据被误改造成登录不可用,可由有权限的运维在数据库中将 login_captcha_policy 的相应模式恢复 image 并递增 version。不要在腾讯云控制台启用尚未接入的可选「CaptchaAppId 强制校验」。
## 验证流程
- 原 /captcha 接口由服务器选择模式;image 返回 PNG,tencent 只返回对应端公开 CaptchaAppId、随机 captcha_id 和两分钟有效期,不返回密钥或答案。
- 挑战存 Redis,绑定会话、客户端类型及策略版本;刷新替换旧挑战,每次校验均消费挑战。
- Web 使用动态加载 TJCaptcha.js 返回 ticket+randstr,后端调用 DescribeCaptchaResult。
- 微信插件返回 ticket,后端调用 DescribeCaptchaMiniResult。两端 AppId/密钥不可混用。
- 短信发送及密码登录请求携带 captcha_ticket(Web 另带 captcha_randstr);保留原 captcha_code 支持 image。模式由服务器决定,客户端不能选择降级。
- 只接受云端 CaptchaCode=1;Web 还拒绝非零 EvilLevel。拒绝 trerror 容灾票据、错误、超时、重复票据;腾讯云请求不自动重试。票据摘要用 Redis SetNX 全局去重十分钟。
- 用户 IP 从直接连接或受信任反向代理链提取,忽略来自不可信连接的转发头。保留短信全局、手机号、会话、IP 限额及发送幂等性。
## 验证记录
- Go 全仓编译通过(`go test ./... -run '^$'`)。
- 配置文件解析、独立 AppId、腾讯云 SDK 分流、失败关闭、受信代理 IP 单测通过。
- 使用隔离 PostgreSQL/Redis、完整迁移 1–71 和 local_seed,`go test ./internal/onboarding -count=1` 通过;包含切换权限、未配置禁止启用、版本冲突、审计、跨端及过期挑战拒绝、票据重放、短信幂等。
- 现有 phone-password-login 浏览器测试通过;新增 tencent-captcha 浏览器测试覆盖取消、容灾票据拒绝、短信/密码分流、切回图片、管理端保存与刷新。腾讯 SDK/API 使用测试替身,不产生验证码或短信费用。
- 小程序 117 个测试、build、check、原生 WXML/WXSS 编译通过;新增插件回调、取消、错误、密码登录和页面离开测试。
官方参考:[Web](https://cloud.tencent.com/document/product/1110/36841)、[微信插件](https://cloud.tencent.com/document/product/1110/49319)、[Web 服务端](https://cloud.tencent.com/document/api/1110/36926)、[小程序服务端](https://cloud.tencent.com/document/product/1110/75490)。