feat(server,web,shared,desktop): 上传超限正确报错 + 两个登录入口都限流 + 作业按天深链,文档与验证脚本同步
服务端加固: - express.json 上限 2mb → 12mb:表格导入把文件以 base64 放进 JSON(约 4/3 倍), 8MB 的声明上限原先到 1.5MB 就被拦掉;超限现在由 error 中间件映射成 413 IMPORT_TOO_LARGE(中文提示"请拆分后分批导入"),不再落进 500 兜底分支抛英文原文; - loginRateLimiter 同时挂 /auth/login 与 /auth/class-login(班级密码默认 123456, 班级登录曾是唯一没有暴力破解防护的入口),两个路径共享同一计数器; - CORS_ORIGIN=* 时启动告警(不拦截启动,避免挡住教室机 file:// 的合法部署); - 删除已无用的 DEFAULT_STUDENT_PASSWORD;班级 termWeeks 上限 40 → 30, 与 MAX_TERM_WEEK / weekNumberSchema 对齐(原先对外承诺了系统兑现不了的学期长度)。 Web 端: - 作业页 ?date= 深链在同路由再推 query 时也生效(watch route.query.date); - 表格导入对话框适配 8MB 上限与 413 提示。 冒烟与文档: - 新增 scripts/lib/smoke-class.mjs:验证用临时班级,避免探针通知弹到用户自己的客户端与灵动岛; - README 与 AGENTS.md 同步本轮全部行为变更(含 schedule source、学生账号清理、凭据门禁)。
This commit is contained in:
1 parent
3880eee08e
commit
20fcca0388
28 files changed
+1649
-915
No files matched your search
@@ -27,7 +27,6 @@ const envSchema = z.object({
|
||||
JWT_EXPIRES_IN: z.string().default('7d'),
|
||||
CORS_ORIGIN: z.string().default('*'),
|
||||
BCRYPT_ROUNDS: z.coerce.number().int().min(4).max(15).default(10),
|
||||
DEFAULT_STUDENT_PASSWORD: z.string().min(6).default('123456'),
|
||||
/** 新建班级时的默认班级密码(学生端班级账号登录用),管理员可随时重置 */
|
||||
DEFAULT_CLASS_PASSWORD: z.string().min(6).default('123456'),
|
||||
/** 新建/重置教师账号时的默认密码(管理员录入教师用) */
|
||||
@@ -109,6 +108,22 @@ if (isProduction) {
|
||||
'请修改 packages/server/.env 后重试。',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* CORS 默认值告警(**不拦截启动**)。
|
||||
*
|
||||
* `CORS_ORIGIN=*` 与 `credentials: true` 同时开启时,cors 中间件会反射请求方 Origin 并带上
|
||||
* `Access-Control-Allow-Credentials: true`。本项目的鉴权走 `Authorization` 头(不是 cookie),
|
||||
* 第三方页面拿不到用户的 token,因此实际风险有限;但"允许任意站点带凭据访问"是没有必要的暴露面,
|
||||
* 生产部署应填成实际域名。这里只告警:真要卡死会挡住"教室机 file:// 页面直连后端"这类合法部署
|
||||
* (那类请求的 Origin 是 `file://`,无法提前枚举),代价不值得。
|
||||
*/
|
||||
if (raw.CORS_ORIGIN.trim() === '*') {
|
||||
console.warn(
|
||||
'⚠ CORS_ORIGIN=* 且已开启 credentials:生产环境建议改成具体来源(逗号分隔),' +
|
||||
'例如 CORS_ORIGIN=https://your-domain.example(教室机 file:// 客户端不受影响)。',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/** trust proxy 支持 false / 数字跳数 / loopback 等字符串形式 */
|
||||
@@ -142,7 +157,6 @@ export const env = {
|
||||
.filter(Boolean),
|
||||
bcryptRounds: raw.BCRYPT_ROUNDS,
|
||||
/** 新增学生时未指定密码时的初始密码 */
|
||||
defaultStudentPassword: raw.DEFAULT_STUDENT_PASSWORD,
|
||||
/** 新建班级时的默认班级密码(班级账号登录) */
|
||||
defaultClassPassword: raw.DEFAULT_CLASS_PASSWORD,
|
||||
/** 新建/重置教师账号时的初始密码 */
|
||||
|
||||
Reference in new issue
Block a user