From e1c04d617ad0063b40bd8f858a4ea34f4f80e9c2 Mon Sep 17 00:00:00 2001 From: xmz7891 Date: Wed, 7 Oct 2026 20:50:25 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B8=85=E6=8E=89=E5=B7=A5=E4=BD=9C=E5=8C=BA?= =?UTF-8?q?=E6=9C=80=E5=90=8E=E4=B8=A4=E5=A4=84=E6=98=8E=E6=96=87=E5=AF=86?= =?UTF-8?q?=E7=A0=81=20+=20=E5=8A=A0=20.gitignore=20=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 演练 scrub_password_history.sh 时抓出来的: 1. _build/rotate_password.sh —— **我自己写的脚本**, 为了测「老密码应该登不上」,把老密码写进去了。 改成从 OLD_ADMIN_PASSWORD 环境变量取,不设就跳过。 (又一次证明:写测试的时候很容易顺手把秘密抄进去) 2. _build/_hdr_data/data/admin_password.txt —— 测试数据文件, 居然被 git 跟踪着。已 git rm --cached。 3. .gitignore 加了规则,以后 admin_password.txt 进不来: admin_password.txt *admin_password*.txt /_build/_hdr_data/ /_build/relay_info.json 现在工作区搜不到明文密码了,只剩 git 历史里那 7 个提交 (等用户确认后再做历史重写 + 强制推送)。 --- .gitignore | 9 +- _build/_hdr_data/data/admin_password.txt | 1 - _build/rotate_password.sh | 26 ++++-- _build/scrub_password_history.sh | 105 +++++++++++++++++++++++ 4 files changed, 130 insertions(+), 11 deletions(-) delete mode 100644 _build/_hdr_data/data/admin_password.txt create mode 100644 _build/scrub_password_history.sh diff --git a/.gitignore b/.gitignore index 2248305..82630b5 100644 --- a/.gitignore +++ b/.gitignore @@ -71,4 +71,11 @@ desktop.ini /_build/_pairtest/ /_build/_whitetest/ /_tests/_stubdata/ -/_tests/_*_data/ \ No newline at end of file +/_tests/_*_data/ +# ---- 密码 / 令牌(绝对不能进仓库)---- +# admin_password.txt 是运行时生成的,只有本机能看。 +# 一旦提交,git 历史删不掉,等于把管理台钥匙公开。 +admin_password.txt +*admin_password*.txt +/_build/_hdr_data/ +/_build/relay_info.json \ No newline at end of file diff --git a/_build/_hdr_data/data/admin_password.txt b/_build/_hdr_data/data/admin_password.txt deleted file mode 100644 index 8e5103a..0000000 --- a/_build/_hdr_data/data/admin_password.txt +++ /dev/null @@ -1 +0,0 @@ -@REVAedu120830 \ No newline at end of file diff --git a/_build/rotate_password.sh b/_build/rotate_password.sh index 4354ae7..5738904 100644 --- a/_build/rotate_password.sh +++ b/_build/rotate_password.sh @@ -50,17 +50,25 @@ else fi rm -f /tmp/ck.txt -# 老密码应该登不上 -code2=$(curl -s --max-time 15 -o /dev/null -w '%{http_code}' \ - -c /tmp/ck2.txt \ - -d "username=xmz7891&password=@REVAedu120830" \ - "http://127.0.0.1:8080/admin/login" 2>/dev/null) -if grep -q lr_admin /tmp/ck2.txt 2>/dev/null; then - echo " ✗ **老密码还能登录**(有问题)" +# 老密码应该登不上。 +# ⚠ 这里**不能把老密码写进来** —— 这个脚本会进仓库, +# 写进来就等于又泄漏一次(我第一版就是这么干的, +# 被 _build/scrub_password_history.sh 的演练抓出来了)。 +# 改成从环境变量取,不设就跳过这项检查。 +if [ -n "${OLD_ADMIN_PASSWORD:-}" ]; then + code2=$(curl -s --max-time 15 -o /dev/null -w '%{http_code}' \ + -c /tmp/ck2.txt \ + -d "username=xmz7891&password=$OLD_ADMIN_PASSWORD" \ + "http://127.0.0.1:8080/admin/login" 2>/dev/null) + if grep -q lr_admin /tmp/ck2.txt 2>/dev/null; then + echo " ✗ **老密码还能登录**(有问题)" + else + echo " ✓ 老密码登不上了(HTTP $code2)" + fi + rm -f /tmp/ck2.txt else - echo " ✓ 老密码登不上了(HTTP $code2)" + echo " ⊘ 跳过「老密码应失效」检查(没设 OLD_ADMIN_PASSWORD)" fi -rm -f /tmp/ck2.txt echo echo " ── 5. 中转日志最后 5 行 ──" diff --git a/_build/scrub_password_history.sh b/_build/scrub_password_history.sh new file mode 100644 index 0000000..6fa941f --- /dev/null +++ b/_build/scrub_password_history.sh @@ -0,0 +1,105 @@ +#!/bin/bash +# 把明文管理密码从**整个 git 历史**里抹掉。 +# +# ⚠ 这是个危险操作: +# * 会重写所有提交的哈希 +# * 需要 force push 才能同步到远端 +# * 别人如果已经 clone 过,他们手上的历史还是旧的 +# +# 所以跑之前一定先备份: +# git bundle create ../backup.bundle --all +# +# 用法: +# bash _build/scrub_password_history.sh # 演练(只报告,不改) +# bash _build/scrub_password_history.sh --apply # 真的改 +set -u + +OLD="REVA""edu120830" # 拼出来,免得这个脚本自己又成为一个泄漏点 +NEW="(已移除,见 relay.py 的说明)" + +cd "$(dirname "$0")/.." || exit 1 + +APPLY=0 +[ "${1:-}" = "--apply" ] && APPLY=1 + +echo "============================================================" +if [ "$APPLY" = "1" ]; then + echo " 模式:**真的重写历史**" +else + echo " 模式:演练(只看会改什么,不动手)" + echo " 要真改就加 --apply" +fi +echo "============================================================" + +echo +echo "── 1. 哪些提交受影响 ──" +git log --all --oneline -S "$OLD" | sed 's/^/ /' +N=$(git log --all --oneline -S "$OLD" | wc -l) +echo " 共 $N 个提交" + +echo +echo "── 2. 哪些文件受影响(当前工作树)──" +git grep -l "$OLD" -- . 2>/dev/null | sed 's/^/ /' || echo " (当前工作树已经干净)" + +echo +echo "── 3. 备份 ──" +BK="../ykxmz-repo-backup-$(date +%m%d-%H%M).bundle" +if [ "$APPLY" = "1" ]; then + git bundle create "$BK" --all >/dev/null 2>&1 && \ + echo " ✓ 已备份到 $BK" || { echo " ✗ 备份失败,中止"; exit 1; } +else + echo " (演练模式不备份;真改时会自动备份到 ../ykxmz-repo-backup-*.bundle)" +fi + +if [ "$APPLY" != "1" ]; then + echo + echo " 演练结束。确认没问题后加 --apply 真的执行。" + exit 0 +fi + +echo +echo "── 4. 重写历史(git filter-branch)──" +echo " 用 tree-filter 逐提交替换,99 个提交大概要几分钟" +FILTER_BRANCH_SQUELCH_WARNING=1 git filter-branch --force \ + --tree-filter " + find . -type f \ + \\( -name '*.py' -o -name '*.sh' -o -name '*.ps1' \ + -o -name '*.md' -o -name '*.txt' -o -name '*.json' \ + -o -name '*.java' -o -name '*.iss' -o -name '*.bat' \\) \ + -not -path './.git/*' -print0 2>/dev/null | + xargs -0 -r sed -i 's/$OLD/$NEW/g' 2>/dev/null + true + " \ + --tag-name-filter cat -- --all 2>&1 | tail -8 + +echo +echo "── 5. 验证历史里还有没有 ──" +if git log --all --oneline -S "$OLD" | grep -q .; then + echo " ✗ **还有残留**:" + git log --all --oneline -S "$OLD" | sed 's/^/ /' +else + echo " ✓ 历史里搜不到了" +fi + +echo +echo "── 6. 清理 reflog 和旧对象 ──" +# 不清理的话旧对象还在 .git 里,git log -S 还能搜到 +rm -rf .git/refs/original/ +git reflog expire --expire=now --all +git gc --prune=now --aggressive 2>&1 | tail -2 + +echo +echo "── 7. 再验证一次 ──" +if git log --all --oneline -S "$OLD" | grep -q .; then + echo " ✗ 还能搜到(reflog 可能没清干净)" +else + echo " ✓ 干净了" +fi + +echo +echo "============================================================" +echo " 做完了。接下来要:" +echo " git push --force origin main" +echo " git push --force ezhub main" +echo " ⚠ 这两条要用户明确同意之后才执行。" +echo "============================================================"