security: 改密即吊销全部旧令牌 + 登录防爆破 + COS 异地备份(环境变量开关) + 启动失败重试按钮

This commit is contained in:
root
2026-10-17 10:59:25 +08:00
parent 56a60d5dc1
commit 08b0317d35
8 changed files with 133 additions and 18 deletions
+8 -1
View File
@@ -26,7 +26,8 @@ async function main() {
check('错误密码登录 401', bad.status === 401, bad.status)
const ok = await post('/api/auth/login', { username: 'audit_a', password: 'aapass123' })
check('正确密码登录 200', ok.status === 200 && !!ok.body.token, ok.status)
const tokA = reg.body.token, tokA2 = ok.body.token
let tokA = reg.body.token
const tokA2 = ok.body.token
const noAuth = await post('/api/sync', { tables: {} })
check('无 token 同步被拒 401', noAuth.status === 401, noAuth.status)
const regB = await post('/api/auth/register', { username: 'audit_b', password: 'bbpass123' })
@@ -85,6 +86,10 @@ async function main() {
check('旧密码立即失效 401', oldLogin.status === 401, oldLogin.status)
const newLogin = await post('/api/auth/login', { username: 'audit_a', password: 'aapass456' })
check('新密码登录 200', newLogin.status === 200, newLogin.status)
// 改密后旧令牌立即失效(会话吊销)
const oldTokSync = await post('/api/sync', { tables: {} }, tokA)
check('改密后旧 token 同步被拒 401', oldTokSync.status === 401, oldTokSync.status)
tokA = newLogin.body.token
const chgWrong = await post('/api/auth/password', { oldPassword: 'zzz', newPassword: 'whatever1' }, tokA)
check('错误旧密码改密被拒 400', chgWrong.status === 400, chgWrong.status)
@@ -123,6 +128,8 @@ async function main() {
check('注册表仅存哈希不存明文密码', !!aRec && !JSON.stringify(aRec).includes('aapass'))
await new Promise(r => globalThis.setTimeout(r, 400))
check('启动自动备份已生成', fsMod.existsSync('server/data/backups/' + new Date().toISOString().slice(0, 10) + '/registry.json'))
const hInfo = await fetch(BASE + '/api/health').then(x => x.json()).catch(() => ({}))
check('health 暴露备份状态', hInfo && hInfo.backup === 'local-only', hInfo.backup)
const d1 = await post('/api/auth/delete', {}, tokA)
check('删除账号 200', d1.status === 200, d1.body)