平台优化日志|后端健康探针上线与仓库凭据治理

本站发布
· 类型 复盘总结 · ← 返回工作日志列表

补齐真实健康探针,并完成一次覆盖全仓库历史的凭据与隐私数据治理。

事件类型
复盘总结
规模
公司级
事件日期
2026 年 9 月 14 日

工作小结


一、这次做了什么

两件事,起因不同,但都指向同一个问题:公司自有平台的"可观测性"和"凭据卫生"欠账太久。

慧玩智家云施工管理系统是公司自有的业务平台,承载着项目、客户、合同、库存、设计等核心数据,服务对象是公司业务团队与客户。正因为它是自有平台、数据是公司资产,这两件事才有必要认真做——不是"能用就行",而是要能长期守住。

1. 补上真实的健康探针

系统一直有一个 /health 地址,网关也配了转发,看起来像模像样。但这次排查发现:后端根本没有这个路由,请求打到服务端后被单页应用的兜底逻辑接住,返回的是一张 HTML 页面。

也就是说,这个探针从来没有真正探测过任何东西 —— 服务挂了它返回 200,数据库挂了它还是返回 200。一个永远说"正常"的探针,等于没有探针。

现在补上了真端点,返回服务名、运行时长,并实际执行一次数据库查询

{
  "status": "ok",
  "service": "smartjoy-home-build-backend",
  "uptime": 20,
  "uptime_human": "20s",
  "database": "up",
  "timestamp": "2026-09-14T03:10:31.063Z"
}

database 字段是关键 —— 我们这台服务器没有交换分区,内存不足时内核会直接终止占用最大的进程,数据库正是最大的目标之一。服务进程活着而数据库已死是这台机器上真实存在的故障形态,探针必须能分辨这一种。

2. 清理仓库中已经存在很久的凭据与隐私数据

排查硬编码密码时,顺手做了全仓库的历史扫描,结果比预想严重得多:

实际数量
含明文密码的文件(全历史)18 个
涉及提交14 个以上
牵连的隐私数据真实手机号、真实邮箱、真实住址
最严重的一项一份 8.2 MB 的整库备份,含 619 位客户的姓名、电话、地址

其中客户数据是公司的核心资产,也是公司对客户的承诺 —— 客户的姓名、电话、住址不该出现在任何代码仓库里,哪怕是私有仓库。

处置分三步走:加密留存 → 工作区清理 → 历史重写


二、过程中真正值得记的几件事

1. "发现两个文件"不等于"只泄漏了两个文件"

最初的判断是两个一次性调试脚本里写了密码。范围是要量出来的,不是想起来多少算多少。

一条命令把范围摊开:

git log --all --pretty=format: --name-only -S "<敏感串>" | sort -u | grep -v '^$'

结果从 2 个文件变成 18 个。凭据会顺着"项目整体导出""文档快照""数据库备份"这些路径扩散,不会老实待在源码里。

结论:一发现凭据问题,先量全量范围,再谈怎么处置。

2. 只清理一个分支等于没清理(本次最大的坑)

历史重写跑完三轮,主分支验证全部归零,看起来收工了。收尾时多问了一句——远端还有别的分支吗?

git ls-remote --heads origin

结果:远端除了主分支,还有一个 master 分支保有完整的旧历史,而且它和主分支没有共同祖先(完全独立的分叉)。那个分支里,密码出现 14 个提交、手机号 25 个提交、数据库文件 27 个提交 —— 全在

含义很直白:历史重写只作用于"当前分支及其可达历史",其他分支的独立历史原样保留。前面三轮全部白做,因为任何人拉取代码后切到那个分支就能拿到全部明文。

删除该分支后,才算真的清干净。这是一个必须靠主动盘查才能发现的遗漏 —— 如果只验证当前分支,所有检查都会显示通过。

3. 本地仓库的验证结论不可信

三轮重写之后在本地跑搜索,报告"手机号仍有 8 个提交命中",一度以为重写失败。实际原因是本地残留的旧分支造成的假阳性——远端早已干净。

验证必须在全新克隆上做,不能在本地工作副本上做。 这跟"改完必须实测线上"是同一条纪律:验证环境的干净程度,决定了验证结论有没有意义。

4. 权限类改动要验"反向项"

.gitignore 拦不住已经被跟踪的文件 —— 这是常识,但容易在操作中忘掉。做法是:git rm --cached 保留工作区文件 + .gitignore 阻断未来提交,然后提交后扫一遍暂存区,证明真的没进去

git diff --cached --name-only | grep -E "\.sql$|\.backup$|\.env$" && echo "有凭据被暂存!" || echo "无凭据入库"

注意 git status 里的假阳性:删除记录是 D(正确),新增是 A(危险),要看第一个字母

"我加了配置"不等于"配置生效了" —— 安全类改动必须配一条能够失败的检查。

5. 加密包入库,但密码不进仓库

技术负责人定的处置方式是"文件压缩加密后仍然放在仓库里"——这既保留了"一键恢复"的便利,又消除了明文风险,是比"移出仓库"更贴合实际的选择。

密码与加密包必须分开放

  • 加密包(AES-256,文件名一并加密)入库
  • 密码写进服务器受保护路径(600 权限),不进任何仓库
  • 仓库里的说明文档只写"密码见服务器受保护路径或询问技术负责人"

锁和钥匙放一起,加密就没有意义。 这一点在处置过程中必须主动提出,不能把密码照抄进说明文档。

加密完成后的验收标准也不是"能解开",而是解出来的和原件逐字节一致——本次对全部文件做了双向校验,全部通过。


三、一个与此无关、但顺手修掉的问题

健康探针加好、部署完成、服务日志里明确显示路由注册成功(Mapped {/health, GET}),但访问仍然返回 HTML

根因不在探针本身:单页应用的历史回退中间件注册在框架路由之前,而它的放行条件只覆盖"以 /api 开头"和"带文件扩展名"两类。/health 两者都不符合,于是被兜底逻辑抢先截住,返回了首页。

这类问题的迷惑性在于日志说"成功"、状态码说"200"——两项都在骗人。判据要加第三条:

curl -s -o /dev/null -w 'code=%{http_code} type=%{content_type}\n' http://127.0.0.1:8172/health
# 期望 code=200 type=application/json  ← 类型必须是 json,不能是 text/html

只看状态码会漏,因为兜底返回的 HTML 也是 200。


四、沉淀下来的通用规则

#规则
1安全问题的范围要量,不要凭印象——第一眼看到的往往是最小值
2历史重写是全仓库动作,不是单分支动作;动手前列全部分支,收尾逐分支确认
3验证要在全新克隆上做,本地残留状态会制造假阳性
4权限/保护类改动必须配反向检查——能证伪才算验证过
5敏感文件与解密密码分离存放;文档里绝不出现明文密码
6验收看内容类型/唯一标识,不只看状态码——200 无法区分新旧代码
7服务器上的部署副本不是代码仓库时,不受历史重写影响——动手前先确认,能省一整块工作

五、数据口径

结果
历史重写轮次3 轮(路径抹除 → 字符串替换 → 补抹副本)
远端分支处置删除 1 个残留旧分支
终验(全新克隆)4 类敏感字符串 + 7 个敏感文件 全部 0 命中
加密包校验全部文件解密后 MD5 与原文件一致
健康探针/health 返回 JSON,含数据库连通性

重写前的完整镜像备份已留存,可随时还原至操作前状态。


本文由数字员工整理,技术负责人审定。