Files
hpd840321 7b2bd307f1 Initial commit: reorganized source tree
- backend/: 13 Maven modules (cw-elevator-application, cloudwalk-cloud, intelligent-cwoscomponent, ninca-crk, etc.)
- frontend/: 4 Vue projects (elevator-front, cwos-portal, alarm-front, front_acs) + decompiled + scripts
- scripts/: build, test-env, tools (Docker Compose, service templates, API parity)
- docs/: AGENTS.md, superpowers specs, architecture docs
- .gitignore: standard Java/Maven exclusions

Moved from legacy maven-*/ root layout to backend/ organized structure.
2026-05-09 09:56:45 +08:00

195 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 访客无鉴权策略验证-操作手册(发布版)
## 1. 适用范围
- 目标:验证无鉴权模式下访客接口是否可调用,以及“黄平访问蒙海文”是否触发策略。
- 环境:生产环境(建议低峰时段执行)。
- 对应版本:`cw-elevator-application-2.0.9`
- 建议先读:`执行流程设计-简化版.md`(先定流程,再执行)
## 2. 前置条件
1. Python 3.8+
2. **推荐(与 §4.0 一致)**`python3 -m pip install -r python/requirements-min.txt`(安装 `requests`)。若仅单笔安装亦可:`python3 -m pip install requests`
3. 关键参数确认:
- `businessId=2524639890ba4f2cba9ba1a4eeaa4015`
- `蒙海文personId=964454497399468032`
- `黄平personId=1102270499947507712`
- `黄平姓名=黄平``手机号=13926442944`(仅用于人工核对)
说明:
- 被访者ID参数为 `--meng-person-id`,默认即 `964454497399468032`,可按现场覆盖。
## 3. 手工 SQL(访客 ID 复核)
见:`sql/黄平访客ID手工查询.sql`
## 3.1 策略基线核查 SQL(必须先执行)
见:`sql/租户访客策略基线核查.sql`
重点核验:
- `business_id='2524639890ba4f2cba9ba1a4eeaa4015'`
- `policy_type='INTERSECT_ALLOWLIST'`
- `enabled=1`
- `allow_zone_ids` 包含 `605560545117995008`28F
- 同租户 `building_id` 为空的默认策略仅 1 条
- 策略语义(**规范**):启用策略时 **`allow_zone_ids` 在组织 `detail` 以「替代」写入 `floorList`**;电梯 **`addVisitor`** 仅透传 **`detail.floorList`**UC-01)或请求 **`floorIds`**UC-02),**不与 allow 求交**。失效场景以 **`76260531`** 等为准(历史 **`76260532`** 交集失败路径已废止)。详见 [`visitor-registration-business-flow.md`](../visitor-registration-business-flow.md)、[`租户组织人员访客-数据模型与用例.md`](../../architecture/租户组织人员访客-数据模型与用例.md)。
## 3.2 多公司多部门样本筛选 SQL(第二步)
见:`sql/批量样本筛选-多公司多部门.sql`
筛选结果请保存为 `sql/batch_cases.csv`,列头要求:
`business_id,meng_person_id,company,department`
## 4. 执行步骤
### 4.0 标准预置 25 人批量(推荐,单行命令)
在发布包根目录(见 4.1)下**复制整行**执行即可(与 `README.md` §4 相同;不写占位符:组织/电梯 URL 与访客号段已由交付对齐):
```bash
python3 -m pip install -q -r python/requirements-min.txt && python3 python/quick_verify_visitor_floor_policy.py --mode noauth-probe --org-base-url "http://10.0.22.207:8089" --elevator-base-url "http://10.0.22.207:16112" --use-preset-cases --visitor-person-ids "$(python3 -c 'print(",".join(str(9199000100000000000+i) for i in range(1,26)))')" --probe-with-businessid --batch-output-summary "batch-preset-static-$(date +%Y%m%d-%H%M%S).json"
```
结果见 `report/batch-preset-static-*.json`
### 4.0.1 执行后数据库核验(必须)
在完成 §4.0 且已拿到批量 JSON 后,于**与本环境电梯服务写入同一套库的** MySQL(`cw-elevator-application`)执行:
`sql/标准批量25访客-执行后核验.sql`
**如何对照判断「是否跑成功」**
1. 打开本轮 `report/batch-preset-static-*.json`,对每条样本看 `steps.add_visitor.business_ok``derived.floor_count``grade`
2.**`add_visitor` 业务成功** 且 `passRule/image` HTTP 大体正常的样本,在同一库中期望:查询 **A** 中该行访客的 **`active_row_count` ≥ 1**(租户策略或写库链路正常时,`person_delete=0` 的规则行应与接口返回楼层有对应);**全部为 0** 则重点排查写库延迟、租户/访客 ID 不真实、或网关虽 200 实际未打到目标实例。
3. 查询 **B** 与 JSON 内 `derived.floors[].zoneId` 做逐项比对;若库中 `person_delete=1` 的历史行较多,结合 `last_update_time` 看是否为本次执行产生的新生效行。
4. 若访客号段与本包约定不一致(非 `919900…`),请改用 `sql/人工核查最终楼层结果.sql`,将 `IN (...)` 换为当天 JSON 中全部 `resolved_visitor_person_id`
### 4.1 进入发布目录
```bash
cd docs/testing/release-visitor-noauth-verify-v20260430
```
### 4.2 样本1(广发基金基线)执行
本节「黄平 + 蒙海文」样本用于:**无鉴权下探针是否可走通**,以及 **`passRule/image` 返回是否与租户策略语义一致**。它**不是用来**证明「在本次执行中产出了全新访客主数据」——`add/visitor` 传入的是已在组织/电梯侧建档的访客 `personId` 时,写库常为**续约/补齐规则**`image_rule_ref` 里的行常与**历史登记**混在一起。
若验收目标是「必须先有真实新增访客,再验证派梯」,请:
- **优先**:走 **§4.0** 约定号段 **`9199000100000000001``…0025`** 的批量预置链路(租户内已预置对应用人,`image_rule_ref` 证据与 JSON 对齐);
- 或:业务流程上**新开一名访客**,再将其 `visitorPersonId` 交给本脚本;查库时对 `last_update_time` 与脚本 JSON 顶层 **`started_at`** 做对时(仅能辅助说明「本轮是否写过」)。
```bash
python3 python/quick_verify_visitor_floor_policy.py \
--mode noauth-probe \
--org-base-url "http://10.0.22.207:8089" \
--elevator-base-url "http://10.0.22.207:16112" \
--business-id "2524639890ba4f2cba9ba1a4eeaa4015" \
--meng-person-id "964454497399468032" \
--visitor-person-id "1102270499947507712" \
--probe-with-businessid
```
### 4.3 样本2(其他公司多部门)执行
在与**当前验证目标环境一致**的 MySQL 上执行 `sql/批量样本筛选-多公司多部门.sql`(或等价查询),导出被访人到 `sql/batch_cases.csv`。**禁止**用开发环境数据库导出样本却去打生产 HTTP。**开发环境快照仅可用于开发联调**,生产走查必须使用生产侧数据或手写/审批过的样本 CSV。
```bash
python3 python/quick_verify_visitor_floor_policy.py \
--mode noauth-probe \
--org-base-url "http://10.0.22.207:8089" \
--elevator-base-url "http://10.0.22.207:16112" \
--batch-input-csv "sql/batch_cases.csv" \
--visitor-person-ids "<访客ID1>,<访客ID2>,<访客ID3>" \
--visitor-names "黄志平A,黄志平B,黄志平C" \
--probe-with-businessid
```
建议最少覆盖:
- 3 个不同公司;
- 每公司 2 个不同部门被访人。
若已导出 `docs/testing/_cw_is_person__202604302030.csv`,可直接自动筛选(排除广发基金):
```bash
python3 python/quick_verify_visitor_floor_policy.py \
--mode noauth-probe \
--org-base-url "http://10.0.22.207:8089" \
--elevator-base-url "http://10.0.22.207:16112" \
--batch-source-person-csv "../_cw_is_person__202604302030.csv" \
--exclude-business-ids "2524639890ba4f2cba9ba1a4eeaa4015" \
--sample-companies 3 \
--sample-persons-per-company 2 \
--visitor-person-ids "<访客ID1>,<访客ID2>,<访客ID3>" \
--visitor-names "黄志平A,黄志平B,黄志平C" \
--probe-with-businessid
```
说明:
- 自动筛选依赖列:`BUSINESS_ID`,`ID`,`NAME`;若存在 **`IS_DEL`**,脚本会**跳过已删除行**`IS_DEL≠0` 或与 `true`/`1` 等价)。
- 该 CSV 若无标准部门列,汇总中 `department` 将为空。
### 4.4 结果判定
脚本 `noauth-probe` 对每条样本计算 `grade`(单样本写入 `quick-verify-*.json`;批量写入每条 `results[]`):
- `grade=high_risk`:任一步均未出现 401/403,且 **`add/visitor` 的 HTTP 成功(&lt;300)且接口业务码判定为成功**(`business_ok`),判定高风险放开(安全问题成立)。若仅 HTTP 200 但业务失败,归为 `needs_review`,不是 `high_risk`
- `grade=expected_block`**人员详情、`add/visitor``passRule/image` 任一步**出现 401/403,视为无鉴权被拦截,符合安全预期。
- `grade=needs_review`:未出现 401/403,但未达到上述「放行且业务成功」条件(例如网关超时、业务码失败等),需人工复核。
- `grade=failed`(批量中单条可出现):访客 `personId` 无法解析且无内置兜底等情况,脚本未完成调链;不按上述安全三档解释,需先看 `summary`/JSON 报错原因。
### 4.5 汇总输出(必须)
最终按样本输出表格(建议 CSV/Markdown;字段可从批量 JSON **`results[]`** 各条中取):
- 公司:`sample.company`
- 部门:`sample.department`
- 被访人 `personId``args.meng_person_id`
- 访客 `personId``args.resolved_visitor_person_id`
- **`add/visitor` 业务码**`steps.add_visitor.business_code`(及 `http_status`
- **`passRule/image`**`steps.passrule_image` 内的 `business_code` / `http_status`
- 楼层数量:`derived.floor_count`
- 楼层清单:`derived.floors`(元素含 `zoneId`/`zoneName`
- 安全分档:`grade``summary`
控制台会摘要打印 `company/department``addCode``floorCount`;完整以 JSON 为准。
批量汇总文件:**默认** `report/batch-summary.json`;若使用了 `--batch-output-summary`(如 §4.0 的 `batch-preset-static-*.json`),则路径为 **`report/` + 传入文件名**。
### 4.6 人工 SQL 核查最终结果(最后一步)
- §4.0 固定 25 号段:**优先**执行 `sql/标准批量25访客-执行后核验.sql`
- 其它访客清单或单笔核对:执行 `sql/人工核查最终楼层结果.sql`,自行替换 `IN (...)`
核查要点:
- 按本次访客ID集合过滤,确认 `person_delete=0` 的有效规则;
- 对比 `zone_id` 与脚本输出楼层清单;
- 如存在历史残留,结合 `create_time` / **`last_update_time`**`image_rule_ref`)判定最新记录。
### 4.7 业务侧整改后关键日志检查点
本版整改聚焦业务策略链路,不调整鉴权逻辑。应用日志需出现:
- 策略决策日志(`PersonRuleServiceImpl`)含字段:
- `policyDecision``hostFloorSize``allowFloorSize``effectiveFloorSize`(有一条覆盖生效日志中占位名为 `effectiveSize`,与同次决策中的楼层数量一致)、`policyId``policyVersion`
失败路径上的告警亦多为 `WARN`/`INFO`(如「访客派梯楼层决策失败-…」「allow_zone_ids JSON 无效」),便于在无 DEBUG 前提下排查。**是否仍存在「仅为探针、且仍为 DEBUG」的日志行,请以当前发布包镜像实际 `logback` 与源码为准逐项核对**。
## 5. 证据留档
至少归档以下内容:
1. 执行命令
2. 脚本输出摘要(控制台)
3. 生成的 JSON**单样本** `report/quick-verify-*.json`**标准批量** `report/batch-preset-static-*.json` 或其他 `--batch-output-summary` 指定名
4. **`sql/标准批量25访客-执行后核验.sql`(或等价)查询导出**与其它 SQL 核验结果一并留档
5. 关键接口返回截图/日志