# 登录验证码切换(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)。