pangu-user-platform/docs/05-模块技术方案/开放API-学生列表授权-技术设计方案.md

153 lines
6.6 KiB
Markdown
Raw Permalink Normal View History

# 开放API-学生列表授权 技术设计方案
> 作者pangu
> 创建时间2026-02-04
> 评审状态:待评审
---
## 一、总体架构
### 1.1 请求链路
```
外部请求 GET /open/api/student/list?pageNum=1&pageSize=10
→ 不经过 Sa-Token 登录校验security.excludes 排除 /open/api/**
→ ApiAuthInterceptor 拦截 /open/api/**
→ 校验 X-App-Id、X-Timestamp、X-Sign
→ 查应用信息、校验接口授权
→ OpenApiStudentController.list() → IPgStudentService.selectPageList()
→ 返回 TableDataInfo<StudentVo>
```
### 1.2 模块与职责
| 模块/组件 | 职责 |
|-----------|------|
| Security 配置 | 将 `/open/api/**` 加入排除路径,不校验登录 |
| ApiAuthInterceptor | 仅对 `/open/api/**` 生效:校验头、签名、接口授权 |
| OpenApiStudentController | 提供 GET `/open/api/student/list`,委托现有 StudentService |
| IPgApplicationService | 新增 selectByAppCode、checkApiPermission新增/编辑时同步 pg_app_api |
| PgAppApiMapper | 新增按 appCode 查授权 api_path 列表方法(联表 pg_api_dict |
| pg_api_dict | 增加「学生列表」开放接口记录api_path=/open/api/student/list |
---
## 二、安全与鉴权
### 2.1 请求头约定
| 请求头 | 必填 | 说明 |
|--------|------|------|
| X-App-Id | 是 | 应用编码appCode |
| X-Timestamp | 是 | 当前时间毫秒时间戳,防重放 |
| X-Sign | 是 | 签名,见 2.2 |
### 2.2 签名算法
1. 将请求参数Query 与 Body仅一层 key-value按参数名 ASCII 升序排序。
2. 拼接为:`key1=value1&key2=value2&...&appSecret=应用密钥`appSecret 为服务端存储的密钥)。
3. 对上述字符串做 **MD5**,结果转为 **大写**,即 X-Sign。
示例GET无 body
- 请求GET /open/api/student/list?pageNum=1&pageSize=10
- 假设 appSecret=abc123
- 参数字符串:`pageNum=1&pageSize=10&appSecret=abc123`
- sign = MD5(参数字符串).toUpperCase()
### 2.3 时间戳防重放
- 服务端收到 X-Timestamp 后,与当前服务器时间比较,若 |now - timestamp| > 5 分钟,返回 400「请求已过期」。
### 2.4 接口授权校验
- 请求 URI 取 path`/open/api/student/list`),与当前应用在 pg_app_api + pg_api_dict 中关联的 api_path 集合比对;不在集合内则返回 403「无权访问该接口」。
---
## 三、接口设计
### 3.1 开放接口:学生列表
| 项目 | 说明 |
|------|------|
| 方法 | GET |
| 路径 | /open/api/student/list |
| 鉴权 | 应用签名 + 接口授权 |
| 参数 | 与现有 /business/student/list 一致studentName、studentNo、schoolId、schoolGradeId、schoolClassId、status 等;分页 pageNum、pageSize |
| 响应 | 与现有一致:`{ code, msg, rows, total }`TableDataInfo |
### 3.2 错误响应
| HTTP 状态 | 场景 | 示例 msg |
|-----------|------|----------|
| 400 | 缺少认证参数 / 时间戳格式错误 / 请求已过期 | 缺少认证参数 |
| 401 | 应用不存在 / 应用已停用 / 签名验证失败 | 签名验证失败 |
| 403 | 未授权该接口 | 无权访问该接口 |
---
## 四、数据与缓存
### 4.1 表使用
- **pg_application**:已有;需按 app_code 查询selectByAppCode
- **pg_api_dict**:已有;需新增一条 api_path=`/open/api/student/list` 的记录,供授权勾选与校验。
- **pg_app_api**:已有;新增/编辑应用时按 apiCodes 写入/更新;鉴权时按 app_id 联表 pg_api_dict 得到 api_path 列表。
### 4.2 授权生效
- 方案 A每次请求查库或查缓存
- 方案 B应用授权变更时更新缓存校验时先查缓存。
本期可采用**不缓存**或**短 TTL如 5 分钟)缓存**「应用授权 path 集合」,技术实现时在 Service 中按 appCode 查授权 path 列表即可;若后续性能有要求再加 Redis。
---
## 五、实现清单
### 5.1 配置
- **application.yml**security.excludes 增加 `/open/api/**`
### 5.2 应用模块application
- **IPgApplicationService**:新增 `PgApplication selectByAppCode(String appCode)`、`boolean checkApiPermission(String appCode, String apiPath)`。
- **PgApplicationServiceImpl**实现上述方法insert/update 时增加对 apiCodes 的处理,同步 pg_app_api先删后插
- **PgApplication**:增加 `@TableField(exist = false) private List<String> apiCodes;`,用于接收前端与返回详情。
- **PgAppApiMapper**:新增方法,如 `List<String> selectApiPathsByAppCode(String appCode)`(联表 pg_api_dict 取 api_path
- **PgAppApiMapper.xml**:对应 SQLa.app_id = app_id 且 a.api_id = d.api_idd.api_path
### 5.3 开放 API 模块(新建或放在 business 下)
- **OpenApiConfig**WebMvcConfigurer注册 ApiAuthInterceptor仅 addPathPatterns("/open/api/**")。
- **ApiAuthInterceptor**preHandle 中取 X-App-Id、X-Timestamp、X-Sign校验时间戳 → selectByAppCode → 校验签名 → checkApiPermission(uri) → 通过则 return true。
- **OpenApiStudentController**GET `/open/api/student/list`,参数与 PgStudentController.list 一致,委托 IPgStudentService.selectPageList。
### 5.4 接口字典数据
- 在 pg_api_dict 中 INSERT 一条api_code=OPEN_STUDENT_LISTapi_name=学生列表api_path=/open/api/student/listapi_method=GETstatus=0。可使用 SQL 脚本或启动时初始化。
### 5.5 前端
- 已有接口授权勾选apiCodes与 apiList 接口;只需保证后端保存/回显 apiCodes 与 pg_app_api 一致即可,无需改前端逻辑(若当前未回显 apiCodes需后端在查询应用详情时填充 apiCodes
---
## 六、调用测试说明
- 提供「开放API-学生列表授权-调用测试说明.md」或同目录下测试脚本
- 签名算法说明与示例(含 GET 示例)。
- 示例:在管理端创建应用并勾选「学生列表」,记录 appCode、appSecret用 curl 或 Postman 调用 GET /open/api/student/list携带正确 X-App-Id、X-Timestamp、X-Sign。
- 预期:授权应用返回 200 与列表数据;未授权或错误签名返回 401/403。
---
## 七、评审要点
1. 开放路径仅限 `/open/api/**`,与现有 /business、/h5 隔离,且不校验用户登录。
2. 签名算法与请求头约定是否满足安全与对接方实现成本平衡。
3. 学生列表参数与响应与现有一致,避免业务逻辑重复。
4. 应用管理侧保存/回显接口授权与 pg_app_api、pg_api_dict 数据一致性。
5. 后续扩展其他开放接口时,仅需在 pg_api_dict 加记录、新增对应 OpenApiXxxController 即可,鉴权与拦截器复用。