From cda1516aeec3dcee91506f012c8fb86069152f40 Mon Sep 17 00:00:00 2001 From: lc Date: Sun, 23 Aug 2026 10:27:35 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BE=9B=E5=BA=94=E5=95=86=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E6=8E=A5=E5=85=A5=E7=BD=91=E5=85=B3=E4=B8=8E=E6=9D=83=E9=99=90?= =?UTF-8?q?=E7=9F=A9=E9=98=B5=EF=BC=88#6191=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...接口接入网关与最小权限矩阵-修改接口-管理后台.md | 169 ++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 changelogs-v2/2026-08/23_6191_供应商管理接口接入网关与最小权限矩阵-修改接口-管理后台.md diff --git a/changelogs-v2/2026-08/23_6191_供应商管理接口接入网关与最小权限矩阵-修改接口-管理后台.md b/changelogs-v2/2026-08/23_6191_供应商管理接口接入网关与最小权限矩阵-修改接口-管理后台.md new file mode 100644 index 00000000..8d0eaa35 --- /dev/null +++ b/changelogs-v2/2026-08/23_6191_供应商管理接口接入网关与最小权限矩阵-修改接口-管理后台.md @@ -0,0 +1,169 @@ +--- +schema: "hl-changelog/v2" +ticket: "6191" +title: "供应商管理接口接入 Gateway 强制认证并启用最小角色权限矩阵" +consumer: "admin" +author: "lc(GIT)" +change_type: "修改接口" +backend_status: "deployed" +gateway_status: "verified" +frontend_status: "not_required" +frontend_owner: "" +frontend_ref: "" +target_release: "" +verified_at: "" +status_note: "PR #6192 与补充 PR #6194 已合并 dev-v3,最终提交 5d144c962 已部署 TEST。真实账号登录及角色切换实测:匿名和伪造身份返回业务码 401;ADMIN、FINANCE、SUPER_ADMIN、CUSTOMIZER 的十项供应商权限分别为 3、9、10、0;越权写入返回 395002/395004;临时身份、日志和精确缓存已清理。无前端、菜单或按钮改动。" +updated_at: "2026-08-23" +base: "dev-v3" +--- + +# 供应商管理:Gateway 强制认证与最小角色权限矩阵 + +本次只改变现有供应商管理接口的入口和服务端授权行为,不新增接口,也不改变请求字段、响应字段或业务错误码。所有 `/admin/supplier/**` 请求现在统一经 Gateway 路由到资源服务,并要求真实管理员登录态;菜单是否可见不再等同于服务端授权。 + +## 关键变化 + +| 场景 | 修改前 | 修改后 | +|------|--------|--------| +| Gateway 路由 | `/admin/supplier/**` 未纳入资源服务路由 | 路由到资源服务并执行强制认证 | +| 未登录或伪造身份头 | 无稳定的供应商入口保护契约 | 统一响应业务码 `401`,请求不会进入供应商业务 | +| 角色授权 | 供应商权限定义与角色绑定不完整 | 按 ADMIN 3 项、FINANCE 9 项、SUPER_ADMIN 10 项、其他角色 0 项收紧 | +| 凭证地址 | 仅依赖业务接口自身行为 | 只有 `supplier:account:proof:read` 才会在账户详情中返回凭证 URL | + +## 变更接口清单 + +以下现有接口均纳入同一 Gateway 路由与权限门禁;入参、出参保持不变。 + +| # | 方法 | 路径 | 权限 | +|---:|------|------|------| +| 1 | GET | `/admin/supplier/items/page` | `supplier:list` | +| 2 | GET | `/admin/supplier/items/list` | `supplier:list` | +| 3 | GET | `/admin/supplier/items/{supplierId}/basic-info/view` | `supplier:view` | +| 4 | POST | `/admin/supplier/items/add` | `supplier:create` | +| 5 | PUT | `/admin/supplier/items/{supplierId}/update` | `supplier:update` | +| 6 | POST | `/admin/supplier/items/{supplierId}/submit` | `supplier:update` + `supplier:approval:submit` | +| 7 | POST | `/admin/supplier/items/{supplierId}/archive` | `supplier:status:manage` | +| 8 | DELETE | `/admin/supplier/items/{supplierId}/del` | `supplier:delete` | +| 9 | GET | `/admin/supplier/items/{supplierId}/approval-records/page` | `supplier:approval:read` | +| 10 | GET | `/admin/supplier/items/{supplierId}/account-info/list` | `supplier:view` | +| 11 | POST | `/admin/supplier/items/{supplierId}/bank-accounts/add` | `supplier:account:manage` + `supplier:approval:submit` | +| 12 | GET | `/admin/supplier/bank-accounts/{accountId}/view` | `supplier:view`;凭证 URL 另需 `supplier:account:proof:read` | +| 13 | PUT | `/admin/supplier/bank-accounts/{accountId}/default/update` | `supplier:account:manage` | + +## 权限矩阵 + +| 权限 | ADMIN | FINANCE | SUPER_ADMIN | CUSTOMIZER/其他 | +|------|:-----:|:-------:|:-----------:|:---------------:| +| `supplier:list` | ✓ | ✓ | ✓ | — | +| `supplier:view` | ✓ | ✓ | ✓ | — | +| `supplier:approval:read` | ✓ | ✓ | ✓ | — | +| `supplier:create` | — | ✓ | ✓ | — | +| `supplier:update` | — | ✓ | ✓ | — | +| `supplier:approval:submit` | — | ✓ | ✓ | — | +| `supplier:account:manage` | — | ✓ | ✓ | — | +| `supplier:account:proof:read` | — | ✓ | ✓ | — | +| `supplier:delete` | — | ✓ | ✓ | — | +| `supplier:status:manage` | — | — | ✓ | — | + +权限同时检查 Gateway 下传的可信角色和 User 权限点。仅有菜单或按钮权限不能绕过服务端门禁,客户端传入的 `X-Admin-Id`、`X-Admin-Role` 也不能替代有效 Token。 + +## 代表性调用与响应 + +### 已登录角色查询供应商列表 + +```http +GET /admin/supplier/items/page?page=1&pageSize=10 +Authorization: Bearer <管理员访问令牌> +``` + +请求无 Body。请求和成功响应结构未变,典型成功包络如下: + +```json +{ + "code": 200, + "message": "成功", + "data": { + "records": [], + "total": 0, + "page": 1, + "pageSize": 10 + }, + "success": true +} +``` + +### 未登录或仅伪造身份头 + +```json +{ + "code": 401, + "message": "缺少有效的 Authorization 头", + "data": null, + "success": false +} +``` + +项目统一包络可能以 HTTP 200 承载业务失败,调用方必须检查 `code` 和 `success`。 + +### ADMIN 尝试创建供应商 + +```json +{ + "code": 395002, + "message": "无权执行该供应商写操作", + "data": null, + "success": false +} +``` + +### FINANCE 尝试归档供应商 + +```json +{ + "code": 395004, + "message": "无权执行该供应商状态操作", + "data": null, + "success": false +} +``` + +## 边界与兼容性 + +- 请求和响应字段、分页参数、供应商状态机、审批语义、错误码均未修改。 +- 未新增 `sys_menu`,也未修改任何前端菜单、按钮或页面;前端无需同步发布。 +- 账户详情中的凭证 URL 只按独立权限裁剪。本工单不新增文件 URL、文件状态或访问归属校验。 +- 本工单只补供应商权限和路由,不扩大到公共 Feign、文件服务或其他业务模块。 +- 无效 Token、伪造身份头和非目标角色均失败关闭,不产生供应商业务写入。 + +## 验证证据 + +- 最终部署提交:`5d144c962c3812d6adf23361e1d9d86ae01f3199`。 +- Gateway 真实请求:匿名与伪造 `X-Admin-*` 身份均返回业务码 `401`;供应商路径命中 `hl-resource-service` 路由。 +- 使用临时 TEST 管理员通过 `/admin/auth/login` 登录,并依次调用 `/admin/auth/switch-role`: + - SUPER_ADMIN:十项权限 `10/10`; + - ADMIN:仅三项读取权限 `3/10`,创建返回 `395002`; + - FINANCE:除生命周期管理外 `9/10`,凭证读取为 `true`,归档返回 `395004`; + - CUSTOMIZER:`0/10`,读取返回 `403`。 +- 当前 TEST 的供应商类型字典基线未初始化,已授权的列表请求在通过 Gateway 与权限门禁后进入既有下游检查并返回 `395039`;该依赖数据不在本工单改动范围。权限链路、拒绝语义和零写入均已实测。 +- 临时管理员、角色关系、登录日志、操作日志及对应 Redis Token/权限缓存均已精确删除;供应商业务表行数前后不变。 +- 自动化回归:Gateway 定向 `8/8`、User 供应商迁移 `5/5`、Resource 供应商 `19/19`;User 全量 `3588`、Resource 全量 `1855`、Gateway 排除既有无关 Fleet 跨库审计后 `80` 项全部通过;24 模块构建通过。 + +## 影响评估 + +- **是否破坏向后兼容**:否。接口字段与业务动作不变,只补齐原本缺失的入口和授权边界。 +- **前端是否必须同步上线**:否。 +- **前端 workaround 清理点**:无;继续使用现有登录 Token,不要自行构造管理员身份头。 + +## 关联 / 联系人 + +### 链接 + +- **Issue**: [#6191](https://git.1814.love:8443/wx/HL/issues/6191) +- **主 PR**: [#6192](https://git.1814.love:8443/wx/HL/pulls/6192) +- **权限元数据补充 Issue**: [#6193](https://git.1814.love:8443/wx/HL/issues/6193) +- **权限元数据补充 PR**: [#6194](https://git.1814.love:8443/wx/HL/pulls/6194) +- **最终合并提交**: [5d144c962](https://git.1814.love:8443/wx/HL/commit/5d144c962c3812d6adf23361e1d9d86ae01f3199) + +### 联系人 + +- **后端负责人**: @lc