diff --git a/AGENTS.md b/AGENTS.md index 7b4e293..cc30312 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -698,8 +698,8 @@ python tools/db.py exec "UPDATE users SET ..." # 写入 > ⚠️ **下面是"骨架节选",不是线上全文** —— 线上配置还包含(2026-09 实测): > 安全响应头(`Strict-Transport-Security` / `X-Content-Type-Options` / `X-Frame-Options` / > `Referrer-Policy` / `Content-Security-Policy-Report-Only`)、 -> **限流 location**(`= /api/pms/auth/login`、`= /api/pms/auth/challenge`,配合 -> `/etc/nginx/nginx.conf` 里的 `limit_req_zone auth_login_zone / auth_challenge_zone / uploads_zone`)、 +> **限流 location**(`= /api/pms/auth/login`、`= /api/pms/auth/challenge`、`/api/pms/cabinets/abstract/`,配合 +> `/etc/nginx/nginx.conf` 里的 `limit_req_zone auth_login_zone / auth_challenge_zone / uploads_zone / scan_abstract_zone`)、 > `location /uploads/`(免认证同源直出 + 限流 + `expires 30d`)、生产侧 `location = /pms { return 301 /pms/; }`、 > 测试侧 `location /h5/`。 > **改动前先拉线上真实文件为准**: @@ -922,8 +922,12 @@ scp -r software/web/dist/* root@118.31.119.206:/data/pms/web/ # 正式环境 ``` ⛔ zone 名要唯一;`limit_req_status 429;` 只需在主配置写一次(已在)。 > 现有 zone(2026-09 实测 4 个):`auth_login_zone` 10r/m、`auth_challenge_zone` 20r/m、 - > `uploads_zone` 120r/m、**`scan_abstract_zone` 30r/m**(扫码查设备 `/api/cabinets/scan/{abstract_id}` - > 与 `/api/cabinets/abstract/{abstract_id}` 这类**免认证**入口,是枚举攻击面)。 + > `uploads_zone` 120r/m、**`scan_abstract_zone` 30r/m** —— 只挂在 + > `location /api/pms/cabinets/abstract/`(**免认证**的扫码查设备入口,无 token 可枚举 `10-%08d`, + > 是真实攻击面)。 + > ⚠️ **`/api/cabinets/scan/{abstract_id}` 不在这个 zone 里**(前缀 `abstract/` 匹配不到 `scan/`)—— + > 它**需登录**、无 token 恒 `401`(与 id 是否存在无关),**不构成枚举信号,故无需限流**。 + > 实测:`scan` 同 IP 60 连发 = `401`×60 / `429`×0;`abstract` 同法 = `404`×23 / `429`×37。 2. **对应的 `conf.d/*.conf` 里给那个 location 挂 `limit_req`**: ```nginx location = /api/pms/ { @@ -938,6 +942,11 @@ scp -r software/web/dist/* root@118.31.119.206:/data/pms/web/ # 正式环境 ⛔ 不要跳过 `-t` 直接 `restart` —— 配置错会让**整站**(含生产域)起不来。 4. 把线上改动同步回 `deploy/nginx/` 的对应文件(见第 10 条),并在报告里注明。 + > 💡 **经验(写限流文档时必守)**:写"某 zone 覆盖某某路径"时,**必须按 `location` 的前缀语义核对, + > 并附实测 `429` 的路径清单** —— 不要按 zone 的名字推断它管谁 + > (`scan_abstract_zone` 这名字本身就极易让人以为它管 `scan`,而它的 `location` 只有 + > `/api/pms/cabinets/abstract/`;`scan/` 落在无 `limit_req` 的通用 `location /api/pms/`)。 + **2.1 微信小程序上传** 小程序构建产物 `dist/build/mp-weixin/` 不上传到服务器,而是通过微信开发者工具上传: