feat(exam/auth): 登录闸门 + 交卷稳定性加固(R4-R8)
R4 登录/交卷背压闸门 - app/middleware/concurrency_guard.js: 新增。超限即 429 + Retry-After(立即拒绝式, 不排队;实测 429 P50=34ms)。RETRY_AFTER 收敛为单一有依据常量 = '2' (≈1.8 个满载窗口;实测 bcryptjs 1129ms / 原生 265ms 每窗口)。 配额:LOGIN_MAX=16 / SUBMIT_MAX=24 / HEAVY_REQ_MAX=20,各 *REQ_MAX 覆盖。 - config/config.default.js: 闸门配额与连接池容量配置;DB dialect 锁 mysql。 R7 顺序红线 + R8 Retry-After 同源 + 原生 bcrypt - 3 处硬编码 '2' 收敛为单一常量;补"勿因换实现而删闸门"红线注释。 - bcryptjs -> bcrypt@6(N-API,Windows/Linux 均免编译;drop-in,存量哈希 $2b$10$ 兼容)。 - app/model/account.js / app/service/auth.js: 同步哈希实现注释(D4 全族 5 处陈旧 SHA256 注释修正)。 答题链路与综合大题 - app/controller/exam.js: 中职/高职综合大题接口(GET big-question / POST big-answer, 逐问 2000 字上限校验);uploadWord 对中职/高职封堵(400)。 - app/service/exam.js: 抽题快照 question_snapshot 落库、答案归集键修正。 - app/controller/auth.js / app/service/auth.js: toClientUser() 唯一出口, 未发布态按组剔除 score,exam_score/word_score/ppt_score 任何情况下不下发。 - app/router.js: 新增大题与管理端路由。 - app/extend/helper.js: 下载文件名 RFC5987 编码(禁双重编码)。 - app.js: 池容量断言按 env 区分单/多 worker(防 dev 假日志)。 验证:ci-gates.sh 9/9 全绿;verify_login_guard.py 28/28(含 D 组变异 9/9); 真实登录/抽题/交卷端到端 code=0;前端构建 BUILD_RC=0。
This commit is contained in:
@@ -3,7 +3,23 @@
|
||||
const crypto = require('crypto');
|
||||
const jwt = require('jsonwebtoken');
|
||||
const fs = require('fs');
|
||||
const bcrypt = require('bcryptjs');
|
||||
// 🔴 R8(2026-09-21):原生 bcrypt(N-API),**不是** bcryptjs。
|
||||
// 原实现 `require('bcryptjs')` 是纯 JS、**同步阻塞事件循环** —— 实测 16 并发 compare
|
||||
// 耗时 1129ms,且期间**心跳达成率 0%**(主线程被冻结 1.1s,无法 accept 新连接),
|
||||
// 这正是登录链路需要"并发闸门"兜底的根因。原生实现走 libuv 线程池:
|
||||
// 同批 compare 265ms(**4.20×**)、心跳持续(环境实测见 probes/_bench_eventloop.cjs)。
|
||||
//
|
||||
// ✅ 兼容性(已验证,drop-in,无需数据迁移):
|
||||
// · API 同形:hash / compare / hashSync / compareSync 均已实测存在;
|
||||
// · 哈希格式同形:产出仍为 `$2b$10$`,与存量 26/26 条完全一致,可互相比对;
|
||||
// · 是 **N-API** 构建(prebuilds 文件名无 ABI 后缀)⇒ node 18(ABI 108) 与
|
||||
// 22(ABI 127) 同一份二进制均可 load;包内自带 win32-x64 与
|
||||
// linux-x64(glibc + musl)预编译 ⇒ 本地与 Linux 生产**均无需编译**。
|
||||
//
|
||||
// ⚠️ 生产部署影响:原生模块**不会**被 rsync 源码带走,服务器须重新 `npm install`
|
||||
// (见交付报告「上线前置」)。⛔ 不要把 `bcryptjs` 残留为依赖 —— 留着只会
|
||||
// 让后人误以为仍在用纯 JS 实现。
|
||||
const bcrypt = require('bcrypt');
|
||||
|
||||
// bcrypt 计算强度(10 轮,登录场景性能与安全的平衡点)
|
||||
const BCRYPT_ROUNDS = 10;
|
||||
|
||||
Reference in New Issue
Block a user