传输加密
This commit is contained in:
+95
-75
@@ -10,9 +10,9 @@
|
||||
2. 解密、校验并保存记录。
|
||||
3. 提供考勤记录和统计数据给 Qt。
|
||||
4. 保存签到时间段配置。
|
||||
5. 保存学生姓名映射和班级名称映射。
|
||||
5. 保存学生档案和班级信息。
|
||||
6. 保存 K210 上传的人脸照片。
|
||||
7. 保存人脸 ID 到真实学号的映射。
|
||||
7. 保存人脸档案中的 face_id 与真实学号绑定关系。
|
||||
8. 维护待删除人脸任务。
|
||||
9. 维护全局同步版本号。
|
||||
10. 提供健康检查、存储状态和时间接口。
|
||||
@@ -79,20 +79,10 @@ idx_records_timestamp(timestamp)
|
||||
| key | value 内容 |
|
||||
| --- | --- |
|
||||
| `time_slots` | 时间段 JSON |
|
||||
| `mapping_config` | 学生姓名、学生班级归属和班级名称映射 |
|
||||
| `sync_request` | K210 同步请求标志 |
|
||||
| `sync_version` | 全局同步版本号 |
|
||||
|
||||
### 4.3 `face_mappings`
|
||||
|
||||
保存 K210 原始 face_id 到真实学号的映射。服务端同时维护结构化主表,避免把学生、照片和人脸绑定关系混在一个配置 JSON 里。
|
||||
|
||||
| 字段 | 含义 |
|
||||
| --- | --- |
|
||||
| `face_id` | K210 本地人脸编号 |
|
||||
| `student_id` | 真实学号 |
|
||||
|
||||
### 4.4 `classes`
|
||||
### 4.3 `classes`
|
||||
|
||||
保存班级基础信息。
|
||||
|
||||
@@ -102,7 +92,7 @@ idx_records_timestamp(timestamp)
|
||||
| `class_name` | 班级名称 |
|
||||
| `updated_at` | 更新时间 |
|
||||
|
||||
### 4.5 `students`
|
||||
### 4.4 `students`
|
||||
|
||||
保存学生基础信息。
|
||||
|
||||
@@ -115,7 +105,7 @@ idx_records_timestamp(timestamp)
|
||||
| `created_at` | 创建时间 |
|
||||
| `updated_at` | 更新时间 |
|
||||
|
||||
### 4.6 `face_profiles`
|
||||
### 4.5 `face_profiles`
|
||||
|
||||
保存 K210 人脸实体与学生绑定关系。`face_id` 保持为 K210 原始编号,绑定学生时只更新 `student_id`,不改本地特征名。
|
||||
|
||||
@@ -128,7 +118,7 @@ idx_records_timestamp(timestamp)
|
||||
| `created_at` | 创建时间 |
|
||||
| `updated_at` | 更新时间 |
|
||||
|
||||
### 4.7 `face_photos`
|
||||
### 4.6 `face_photos`
|
||||
|
||||
保存人脸照片元数据。照片文件仍保存在 `faces/<face_id>.jpg`,不会按学号重命名。
|
||||
|
||||
@@ -140,7 +130,7 @@ idx_records_timestamp(timestamp)
|
||||
| `file_size` | 文件大小 |
|
||||
| `uploaded_at` | 上传时间 |
|
||||
|
||||
### 4.8 `pending_delete`
|
||||
### 4.7 `pending_delete`
|
||||
|
||||
保存等待 K210 删除的任务。
|
||||
|
||||
@@ -153,7 +143,7 @@ idx_records_timestamp(timestamp)
|
||||
| `status` | 状态,默认 `pending` |
|
||||
| `ack_at` | 确认时间 |
|
||||
|
||||
### 4.9 `device_sync_state`
|
||||
### 4.8 `device_sync_state`
|
||||
|
||||
保存各客户端同步状态。
|
||||
|
||||
@@ -186,23 +176,38 @@ $env:ATTENDANCE_CORS_ORIGIN="http://localhost"
|
||||
|
||||
## 6. 鉴权规则
|
||||
|
||||
服务端对大多数接口要求请求头:
|
||||
服务端对业务接口要求请求头:
|
||||
|
||||
```text
|
||||
X-Api-Token: <Token>
|
||||
```
|
||||
|
||||
允许不带 Token 的情况:
|
||||
允许不带 Token 的情况只有 `OPTIONS` 预检请求。
|
||||
|
||||
1. `OPTIONS` 预检请求。
|
||||
2. `GET /api/v1/system/health`。
|
||||
|
||||
除健康检查外,所有 `/api/v1/...` 接口都使用同样的鉴权逻辑。
|
||||
所有 `/api/v1/...` 业务接口都使用同样的鉴权逻辑,包括健康检查。
|
||||
|
||||
## 7. 路由规范
|
||||
|
||||
服务端接口统一使用 `/api/v1/...` 路径。STM32、K210 和 Qt 管理端都通过这一套接口通信。
|
||||
|
||||
## 7.1 加密传输规则
|
||||
|
||||
业务 JSON 接口统一使用 AES-128-CBC + PKCS#7 + Base64。JSON POST 请求体必须携带:
|
||||
|
||||
```text
|
||||
X-Encrypted: AES128-CBC
|
||||
Content-Type: application/octet-stream
|
||||
```
|
||||
|
||||
服务端会先解密请求体,再进入具体业务路由。JSON 响应统一加密返回,并携带:
|
||||
|
||||
```text
|
||||
X-Encrypted: AES128-CBC
|
||||
Content-Type: application/octet-stream
|
||||
```
|
||||
|
||||
人脸照片 JPEG 作为大体积二进制数据保留 `image/jpeg` 原始上传和下载;照片列表、上传结果、人脸档案、删除结果和同步状态等 JSON 数据仍然走加密传输。后续 API 小节中的 JSON 均表示解密后的业务结构,实际传输时按本节规则加密。
|
||||
|
||||
## 8. 核心 API
|
||||
|
||||
以下示例默认服务端地址是:
|
||||
@@ -215,6 +220,7 @@ http://127.0.0.1:8082
|
||||
|
||||
```text
|
||||
GET /api/v1/system/health
|
||||
X-Api-Token: <Token>
|
||||
```
|
||||
|
||||
返回示例:
|
||||
@@ -261,6 +267,7 @@ STM32 使用 `epoch` 转成 UTC+8 时间。
|
||||
```text
|
||||
POST /api/v1/attendance/checkins
|
||||
X-Encrypted: AES128-CBC
|
||||
X-Encrypted-Response: true
|
||||
X-Api-Token: <Token>
|
||||
```
|
||||
|
||||
@@ -319,13 +326,7 @@ GET /api/v1/attendance/records?limit=1000&offset=0
|
||||
]
|
||||
```
|
||||
|
||||
如果请求头带:
|
||||
|
||||
```text
|
||||
X-Encrypted-Response: true
|
||||
```
|
||||
|
||||
服务端会把响应 JSON 加密后以 Base64 返回。Qt 当前普通记录请求没有启用这个请求头。
|
||||
服务端返回 AES 加密后的 Base64 字符串,客户端解密后得到上述 JSON 数组。
|
||||
|
||||
### 8.6 获取统计
|
||||
|
||||
@@ -371,10 +372,11 @@ GET /api/v1/config/time-slots
|
||||
|
||||
```text
|
||||
POST /api/v1/config/time-slots
|
||||
Content-Type: application/json
|
||||
X-Encrypted: AES128-CBC
|
||||
Content-Type: application/octet-stream
|
||||
```
|
||||
|
||||
请求体:
|
||||
请求体解密后的 JSON 结构:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -422,32 +424,53 @@ GET /api/v1/attendance/today?slot_start=08:00&slot_end=09:30
|
||||
|
||||
STM32 开机后用它构建本地今日缓存。
|
||||
|
||||
### 8.12 学生档案和班级名称映射
|
||||
### 8.12 学生档案
|
||||
|
||||
```text
|
||||
GET /api/v1/config/mappings
|
||||
POST /api/v1/config/mappings
|
||||
GET /api/v1/students
|
||||
POST /api/v1/students
|
||||
```
|
||||
|
||||
格式:
|
||||
返回或提交格式:
|
||||
|
||||
```json
|
||||
{
|
||||
"student_name_map": {
|
||||
"20240001": "张三"
|
||||
},
|
||||
"student_class_map": {
|
||||
"20240001": "1"
|
||||
},
|
||||
"class_name_map": {
|
||||
"1": "软件工程一班"
|
||||
}
|
||||
"students": [
|
||||
{
|
||||
"student_id": "20240001",
|
||||
"student_name": "张三",
|
||||
"class_id": "1",
|
||||
"status": "active"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
其中 `student_name_map` 维护学号到姓名,`student_class_map` 维护学号到班级编号,`class_name_map` 维护班级编号到班级名称。保存后会同步写入 `students` 和 `classes`,Qt 的记录列表、筛选、导出优先使用这里维护的学生班级归属。
|
||||
其中 `student_id` 为学号,`student_name` 为姓名,`class_id` 为所属班级编号。保存后服务端写入 `students` 表并提升同步版本。Qt 管理端修改学号前会弹窗提示该操作会影响人脸绑定、考勤显示、班级筛选和导出结果。
|
||||
|
||||
### 8.13 人脸照片
|
||||
### 8.13 班级信息
|
||||
|
||||
```text
|
||||
GET /api/v1/classes
|
||||
POST /api/v1/classes
|
||||
```
|
||||
|
||||
返回或提交格式:
|
||||
|
||||
```json
|
||||
{
|
||||
"classes": [
|
||||
{
|
||||
"class_id": "1",
|
||||
"class_name": "软件工程一班"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
保存班级时服务端写入 `classes` 表并提升同步版本。删除班级前会检查该班级下是否还有未删除学生;如果仍有学生,接口返回失败,避免产生悬空班级归属。
|
||||
|
||||
### 8.14 人脸照片
|
||||
|
||||
照片列表:
|
||||
|
||||
@@ -483,38 +506,35 @@ GET /api/v1/faces/photos/1
|
||||
|
||||
成功时返回 `image/jpeg`。
|
||||
|
||||
### 8.14 人脸 ID 映射
|
||||
### 8.15 人脸档案
|
||||
|
||||
```text
|
||||
GET /api/v1/faces/mappings
|
||||
POST /api/v1/faces/mappings
|
||||
GET /api/v1/face_profiles
|
||||
POST /api/v1/face_profiles
|
||||
```
|
||||
|
||||
格式:
|
||||
返回或提交格式:
|
||||
|
||||
```json
|
||||
{
|
||||
"mappings": {
|
||||
"1": "20240001"
|
||||
}
|
||||
"face_profiles": [
|
||||
{
|
||||
"face_id": "1",
|
||||
"student_id": "20240001",
|
||||
"device_id": "k210-01",
|
||||
"status": "active",
|
||||
"has_photo": true
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
保存映射后服务端会:
|
||||
保存人脸档案后服务端会:
|
||||
|
||||
1. 写入兼容表 `face_mappings`。
|
||||
2. 同步更新结构化表 `face_profiles` 和 `students`。
|
||||
3. 对已取消绑定的人脸仅清空 `student_id`,保留原始照片和 `face_id`。
|
||||
4. 提升同步版本。
|
||||
5. 设置 K210 同步请求标志。
|
||||
|
||||
### 8.15 获取全部学生 ID
|
||||
|
||||
```text
|
||||
GET /api/v1/faces/student-ids
|
||||
```
|
||||
|
||||
从 `students`、`records` 和人脸映射中汇总学生 ID。
|
||||
1. 写入结构化表 `face_profiles`。
|
||||
2. 对已取消绑定的人脸仅清空 `student_id`,保留原始照片和 `face_id`。
|
||||
3. 提升同步版本。
|
||||
4. 设置 K210 同步请求标志。
|
||||
|
||||
### 8.16 删除人脸
|
||||
|
||||
@@ -526,7 +546,7 @@ DELETE /api/v1/faces/20240001?delete_records=true
|
||||
服务端会:
|
||||
|
||||
1. 删除相关照片。
|
||||
2. 删除相关映射。
|
||||
2. 解除 `face_profiles` 中的人脸绑定。
|
||||
3. 如果 `delete_records=true`,删除该学生相关考勤记录。
|
||||
4. 创建 K210 待删除任务。
|
||||
5. 提升同步版本。
|
||||
@@ -538,7 +558,7 @@ DELETE /api/v1/faces/20240001?delete_records=true
|
||||
{
|
||||
"success": true,
|
||||
"photo_deleted": true,
|
||||
"mapping_deleted": true,
|
||||
"profile_unbound": true,
|
||||
"records_deleted": 3,
|
||||
"k210_pending": true,
|
||||
"sync_requested": true
|
||||
@@ -573,8 +593,8 @@ GET /api/v1/sync/state?client=<client>&last_version=<version>
|
||||
| client | 服务端返回内容 |
|
||||
| --- | --- |
|
||||
| `stm32` | `time_slots` |
|
||||
| `k210` | `face_mappings`、`pending_delete`、`delete_tasks` |
|
||||
| `qt` | 记录、统计、时间段、映射、照片列表、学生 ID、人脸映射 |
|
||||
| `k210` | `face_profiles`、`pending_delete`、`delete_tasks` |
|
||||
| `qt` | 记录、统计、时间段、学生档案、班级信息、人脸档案、照片列表、学生 ID |
|
||||
| `all` 或空 | 尽可能返回全部 |
|
||||
|
||||
如果没有变化:
|
||||
@@ -597,7 +617,7 @@ GET /api/v1/sync/state?client=<client>&last_version=<version>
|
||||
"client": "k210",
|
||||
"server_time": "2026-05-01 10:00:00",
|
||||
"state": {
|
||||
"face_mappings": {},
|
||||
"face_profiles": [],
|
||||
"pending_delete": [],
|
||||
"delete_tasks": []
|
||||
}
|
||||
@@ -657,7 +677,7 @@ cd D:\University\graduation\thesis\code\server
|
||||
## 11. 安全注意事项
|
||||
|
||||
1. 默认 Token 已写在代码里,不适合直接暴露公网。
|
||||
2. 当前是 HTTP 明文传输,公网部署建议放到 HTTPS 反向代理后面。
|
||||
2. 业务 JSON 已使用应用层 AES 加密,公网部署仍建议放到 HTTPS 反向代理后面,保护照片二进制、Token 和传输元数据。
|
||||
3. AES Key/IV 是固定值,演示可以,生产环境不建议固定写死。
|
||||
4. SQLite 数据库和照片目录需要定期备份。
|
||||
5. `ATTENDANCE_CORS_ORIGIN` 不建议设置成任意来源。
|
||||
|
||||
Reference in New Issue
Block a user