refactor(密码): 删掉 PASSWORD_HASH_UPGRADE,无条件写 argon2
Some checks failed
Deploy / deploy (push) Has been cancelled
Some checks failed
Deploy / deploy (push) Has been cancelled
上一个 commit 把五个写入点收进 hashPassword,顺手把开关默认值翻成了 true 并 留下 false 分支当退路。这个退路是假的,删掉。 **开关只能拦住将来,修不了已经发生的。** 等真到了要把旧站拉回来的那天,活跃 账号早就都被登录/重置密码升成 argon2 了,这时候设 `=false` 一个也救不回来。 正经退路是切换手册「万一已经改坏了」那节的脚本 —— 拿 `raw_password` 重算 Django 的 `make_password`,能修已经变成 argon2 的账号。留着一个永远轮不到它 上场的开关,只是给后来人多一件要读懂的东西。 删掉的:`config.passwordHashUpgrade`、`hashDjangoPbkdf2` 和它那套 Django 参数 (1200000 迭代 / 22 位 salt / RANDOM_STRING_CHARS)、两个 compose 里的 `PASSWORD_HASH_UPGRADE` env。auth.ts 的登录升级变成无条件。 保留的: - `hashPassword()` —— 虽然现在只是一行 argon2,但「只有一个地方写密码」正是上 一个 commit 的重点。五处各写各的才是当初那个 bug 的根。 - `verifyPassword` 的 **pbkdf2 分支** —— 生产库 1710 个账号全是 Django 写的 pbkdf2(迭代次数 120000~1200000),只会在各自下次登录时才迁移。删了就是 全站登不上。代码注释里写死了这句话。 - 切换手册里的 `raw_password` 恢复脚本,以及回滚流程里新加的「密码要额外处理」 那一步。 ## 验证 改完重跑了一遍关键路径(临时造一个 Django 生成的 120000 迭代老哈希): - 存量账号登录 200 → 哈希变成 argon2 → 再登 200 → 错密码 401 - 后台重置密码 → argon2 → 新密码能登录 - 注册 → argon2 → 能登录 tsc(apps/api) 0 error、check:routes 168 条无遮蔽、vue-tsc 0 error、build 通过、 两个 compose `config -q` 通过。测试用户已删干净。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -51,22 +51,24 @@ pg_dumpall 备份带 30 条 `setval`,而且直接查生产快照里所有序
|
||||
> 于是「登录过新站的学生,回滚之后登不上旧站」—— 一道结构比对发现不了的单向门。
|
||||
> 试跑第一天就撞上了,现象是旧站登录失败 + WS 连不上(Channels 认 session)。
|
||||
>
|
||||
> 已改成 `PASSWORD_HASH_UPGRADE` 控制。
|
||||
> 当时的修法是加 `PASSWORD_HASH_UPGRADE` 开关、默认关闭。
|
||||
>
|
||||
> **⚠️ 2026-08-26 再补两件事。**
|
||||
> **⚠️ 2026-08-26 更新:开关已经删掉,现在无条件写 argon2。**
|
||||
>
|
||||
> **一、当时那次只堵住了登录那一处,门其实一直开着。** 新后端一共五个地方写密码:
|
||||
> 登录时自动升级、注册、管理员改密码、批量导入用户、**重置密码**。
|
||||
> `PASSWORD_HASH_UPGRADE` 只管住了第一处,后面四处无条件写 argon2 —— 也就是说
|
||||
> 开关关着的时候,**老师给学生点一次「重置密码」,那个账号照样回不去旧站**,
|
||||
> 而这恰恰是老师天天在用的功能。现在五处统一走 `auth/password.ts` 的
|
||||
> `hashPassword()`,开关两个方向都是真的。
|
||||
> 两个原因。**一是那个开关一直是假的**:新后端写密码的地方有五个(登录时自动
|
||||
> 升级、注册、管理员改密码、批量导入用户、**重置密码**),开关只管住了第一处,
|
||||
> 后面四处照写 argon2 不误 —— 也就是说开关关得好好的,老师给学生点一次
|
||||
> 「重置密码」,那个账号照样回不去旧站,而这正是老师天天在用的功能。
|
||||
>
|
||||
> **二、旧站已经下线,这个开关的默认值翻成了 `true`。** 也就是默认写 argon2、
|
||||
> 登录时升级存量哈希。**要把旧站拉回来的话,先设 `PASSWORD_HASH_UPGRADE=false`**,
|
||||
> 之后新写的密码就又是 Django 格式的 `pbkdf2_sha256$1200000$…` 了(已用旧后端的
|
||||
> Django 实打双向验过:新后端写的 `check_password` 通过,Django 写的新后端也认)。
|
||||
> 已经被升成 argon2 的存量账号仍然要按下面「万一已经改坏了」那节修。
|
||||
> **二是旧站已经下线**,没有回滚路径要照顾了。五处现在统一走
|
||||
> `auth/password.ts` 的 `hashPassword()`,只有一个地方写密码。
|
||||
>
|
||||
> 真要把旧站拉回来,正经退路是下面「万一已经改坏了」那节的脚本 —— 它拿
|
||||
> `raw_password` 重算 Django 的 `make_password`,能修**已经**变成 argon2 的账号。
|
||||
> 开关只能拦住将来,修不了已经发生的,这也是它不值得留的原因。
|
||||
>
|
||||
> `verifyPassword` 的 pbkdf2 分支**永远保留**:生产库 1710 个账号全是 Django 写的
|
||||
> pbkdf2(迭代次数 120000~1200000),它们只会在各自下次登录时才迁移成 argon2。
|
||||
|
||||
---
|
||||
|
||||
@@ -311,12 +313,10 @@ WebSocket 那个开关是双跑最容易漏的一格:漏了的话页面一切
|
||||
|
||||
- **两边登录态不互通**。旧站是 Django session,新站是 Redis opaque token。
|
||||
学生到 oj2 要重新登录一次,这不是 bug。
|
||||
- **想保住回滚路径就得设 `PASSWORD_HASH_UPGRADE=false`**(2026-08-26 起默认是
|
||||
`true`,因为旧站已经下线)。默认值下,在 oj2 登录过或被改过密码的账号会变成
|
||||
argon2 哈希,**回旧站就登不上了** —— 试跑第一天真撞过,现象是旧站登录失败 +
|
||||
WS 连不上。修复见下面的「万一已经改坏了」。设成 `false` 之后是真安全:注册 /
|
||||
改密码 / 重置密码 / 批量导入写的也都是 Django 格式的 pbkdf2(以前这几条路
|
||||
无视开关直接写 argon2)。
|
||||
- **在 oj2 登录过、注册的、被改过或重置过密码的账号,哈希会变成 argon2,
|
||||
回旧站就登不上了** —— 试跑第一天真撞过,现象是旧站登录失败 + WS 连不上。
|
||||
2026-08-26 起这是无条件行为(`PASSWORD_HASH_UPGRADE` 开关已删,见上面那条
|
||||
补充说明为什么它本来就拦不住)。修复见下面的「万一已经改坏了」。
|
||||
- **同一个库,双写**。结构完全兼容不会写坏,但提交、统计、成就都是**真实数据**,
|
||||
不是沙盒。别拿它做破坏性试验。
|
||||
- 后台判题机列表会出现**两台**(新旧各自心跳),正常。
|
||||
@@ -443,14 +443,14 @@ backend 和判题机再 start 起来。**不需要恢复数据库,不需要动
|
||||
这也是「只换前后端」形态的主要好处:切换和回滚都不碰数据库进程,
|
||||
库出问题的可能性从流程里被整个拿掉了。
|
||||
|
||||
### ⚠️ 回滚成立的前提:`PASSWORD_HASH_UPGRADE=false`
|
||||
### ⚠️ 回滚要额外处理密码
|
||||
|
||||
「不动任何数据」只在这个前提下成立。默认值(`true`,2026-08-26 旧站下线后改的)
|
||||
下,新站登录过、注册的、被老师改过或重置过密码的账号,哈希都会变成 argon2,
|
||||
旧后端验不了 —— 回滚之后那些学生登不上。
|
||||
「不动任何数据」不适用于 `user.password` 这一列。在新站登录过、注册的、被老师
|
||||
改过或重置过密码的账号,哈希已经是 argon2,旧后端验不了 —— 回滚之后那些学生
|
||||
登不上。(2026-08-26 起这是无条件行为,`PASSWORD_HASH_UPGRADE` 开关已删。)
|
||||
|
||||
**真要留回滚路径,先把 `PASSWORD_HASH_UPGRADE=false` 设上再说**,已经变成
|
||||
argon2 的按下面那节修。
|
||||
所以回滚流程里**必须**加一步:按下面那节把 argon2 的账号用 `raw_password`
|
||||
重算回 Django 的 pbkdf2。
|
||||
|
||||
### 万一已经改坏了
|
||||
|
||||
|
||||
Reference in New Issue
Block a user