传输加密

This commit is contained in:
2026-05-04 21:03:06 +08:00
parent 1ff2e6af01
commit e720b1a392
5 changed files with 190 additions and 151 deletions
+95 -75
View File
@@ -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` 不建议设置成任意来源。