170 行
7.5 KiB
Markdown
170 行
7.5 KiB
Markdown
---
|
||
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
|