341 lines
8.9 KiB
Markdown
341 lines
8.9 KiB
Markdown
# 授权文件管理 API 文档
|
||
|
||
## 概述
|
||
|
||
本系统提供基于设备型号和配置文件的授权文件生成功能。手机APP可以通过设备SN号从平台获取对应的授权文件(JSON格式)。
|
||
|
||
## 核心功能
|
||
|
||
1. **授权项管理** - 定义设备可用的功能模块
|
||
2. **配置文件管理** - 设备的技术参数配置
|
||
3. **授权文件生成** - 根据授权项+配置自动生成JSON授权文件
|
||
4. **授权文件下载** - 手机APP通过设备SN获取授权文件
|
||
|
||
## API 接口
|
||
|
||
### 1. 获取授权列表
|
||
|
||
**接口**: `GET /api/licenses`
|
||
|
||
**响应示例**:
|
||
```json
|
||
[
|
||
{
|
||
"id": 1,
|
||
"model": "GD-30",
|
||
"modules": "一维自电/电阻率/激电测试模块, 二维自电/电阻率/激电测试模块",
|
||
"expiry": "2027-04-30",
|
||
"status": "生效",
|
||
"config_id": 5,
|
||
"device_sn": "",
|
||
"license_file": "{...}",
|
||
"created_at": "2026-04-30 16:00:00",
|
||
"updated_at": "2026-04-30 16:00:00"
|
||
}
|
||
]
|
||
```
|
||
|
||
### 2. 创建授权
|
||
|
||
**接口**: `POST /api/licenses`
|
||
|
||
**请求体**:
|
||
```json
|
||
{
|
||
"model": "GD-30",
|
||
"modules": "一维自电/电阻率/激电测试模块, 二维自电/电阻率/激电测试模块, 三维自电/电阻率/激电测试模块",
|
||
"expiry": "2027-04-30",
|
||
"status": "生效",
|
||
"config_id": 5,
|
||
"device_sn": ""
|
||
}
|
||
```
|
||
|
||
**参数说明**:
|
||
- `model`: 设备型号(必填)
|
||
- `modules`: 授权模块列表,多个模块用", "分隔(必填)
|
||
- `expiry`: 到期时间(可选)
|
||
- `status`: 状态,"生效"或"已停用"(可选,默认"生效")
|
||
- `config_id`: 配置文件ID(可选,不传则自动使用最新配置)
|
||
- `device_sn`: 设备SN(可选,用于设备级授权,不填则为型号级授权)
|
||
|
||
**响应示例**:
|
||
```json
|
||
{
|
||
"id": 1,
|
||
"licenseFile": {
|
||
"version": "1.0",
|
||
"generatedAt": "2026-04-30T16:00:00.000Z",
|
||
"deviceModel": "GD-30",
|
||
"deviceSN": "",
|
||
"validUntil": "2027-04-30",
|
||
"status": "active",
|
||
"authModules": [...],
|
||
"config": {...},
|
||
"signature": {...}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3. 更新授权
|
||
|
||
**接口**: `PUT /api/licenses`
|
||
|
||
**请求体**:
|
||
```json
|
||
{
|
||
"id": 1,
|
||
"model": "GD-30",
|
||
"modules": "一维自电/电阻率/激电测试模块, 二维自电/电阻率/激电测试模块",
|
||
"expiry": "2027-04-30",
|
||
"status": "生效",
|
||
"config_id": 5,
|
||
"device_sn": ""
|
||
}
|
||
```
|
||
|
||
**响应示例**:
|
||
```json
|
||
{
|
||
"ok": true
|
||
}
|
||
```
|
||
|
||
### 4. 手机APP获取授权文件 ⭐
|
||
|
||
**接口**: `GET /api/licenses/download?sn={device_sn}`
|
||
|
||
**说明**: 这是手机APP调用的核心接口,根据设备SN号返回对应的授权文件JSON。
|
||
|
||
**查询参数**:
|
||
- `sn`: 设备序列号(必填)
|
||
|
||
**响应示例**:
|
||
```json
|
||
{
|
||
"version": "1.0",
|
||
"generatedAt": "2026-04-30T16:00:00.000Z",
|
||
"deviceModel": "GD-30 Supreme",
|
||
"deviceSN": "GD30-20260430-001",
|
||
"validUntil": "2027-04-30",
|
||
"status": "active",
|
||
"authModules": [
|
||
{
|
||
"id": "1D",
|
||
"name": "一维自电/电阻率/激电测试模块",
|
||
"category": "一维",
|
||
"enabled": true
|
||
},
|
||
{
|
||
"id": "2D",
|
||
"name": "二维自电/电阻率/激电测试模块",
|
||
"category": "二维",
|
||
"enabled": true
|
||
},
|
||
{
|
||
"id": "3D",
|
||
"name": "三维自电/电阻率/激电测试模块",
|
||
"category": "三维",
|
||
"enabled": true
|
||
}
|
||
],
|
||
"config": {
|
||
"name": "CFG-GD30-v2.1",
|
||
"version": "v2.1",
|
||
"emissionParams": {
|
||
"maxVoltage": "1000V",
|
||
"maxCurrent": "10A",
|
||
"waveform": "0+0-",
|
||
"pulseWidth": "0.25s/0.5s/1s/2s/4s/8s/16s/32s/64s"
|
||
},
|
||
"acquisitionParams": {
|
||
"channels": 12,
|
||
"sampleRate": "50Hz、60Hz/50Hz、60Hz、100Hz、1000Hz",
|
||
"voltageRange": "±2.5V、±80V/±80V、±600V",
|
||
"fullWaveform": true
|
||
},
|
||
"networkParams": {
|
||
"wifiSSIDPrefix": "GD30_"
|
||
}
|
||
},
|
||
"signature": {
|
||
"algorithm": "SHA256",
|
||
"value": "a1b2c3d4e5f6...",
|
||
"publicKey": "platform-public-key-placeholder"
|
||
}
|
||
}
|
||
```
|
||
|
||
**错误响应**:
|
||
```json
|
||
// 设备不存在
|
||
{
|
||
"error": "设备不存在"
|
||
}
|
||
|
||
// 无有效授权
|
||
{
|
||
"error": "该设备暂无有效授权",
|
||
"deviceSN": "GD30-20260430-001",
|
||
"deviceModel": "GD-30 Supreme"
|
||
}
|
||
```
|
||
|
||
**查找逻辑**:
|
||
1. 优先查找绑定到具体设备SN的授权(device_sn字段匹配)
|
||
2. 如果没有设备级授权,则查找型号级别的授权(model字段匹配)
|
||
3. 只返回状态为"生效"且未过期的授权
|
||
4. 每次下载都会记录下载日志
|
||
|
||
### 5. 预览授权文件
|
||
|
||
**接口**: `GET /api/licenses/{id}/preview`
|
||
|
||
**说明**: 在管理后台预览授权文件的JSON内容。
|
||
|
||
**路径参数**:
|
||
- `id`: 授权ID
|
||
|
||
**响应**: 与下载接口相同的JSON格式
|
||
|
||
## 授权文件JSON结构说明
|
||
|
||
```typescript
|
||
interface LicenseFile {
|
||
version: string; // 版本号,如 "1.0"
|
||
generatedAt: string; // 生成时间(ISO格式)
|
||
deviceModel: string; // 设备型号
|
||
deviceSN: string; // 设备序列号
|
||
validUntil: string; // 有效期
|
||
status: string; // 状态:"active" 或 "inactive"
|
||
|
||
authModules: Array<{ // 授权模块列表
|
||
id: string; // 模块ID
|
||
name: string; // 模块名称
|
||
category: string; // 分类
|
||
enabled: boolean; // 是否启用
|
||
}>;
|
||
|
||
config: { // 配置参数
|
||
name: string; // 配置名称
|
||
version: string; // 配置版本
|
||
emissionParams: { // 发射参数
|
||
maxVoltage: string; // 最大发射电压
|
||
maxCurrent: string; // 最大发射电流
|
||
waveform: string; // 发射波形
|
||
pulseWidth: string; // 脉宽范围
|
||
};
|
||
acquisitionParams: { // 采集参数
|
||
channels: number; // 通道数
|
||
sampleRate: string; // 采样率
|
||
voltageRange: string; // 电压量程
|
||
fullWaveform: boolean; // 是否支持全波形
|
||
};
|
||
networkParams: { // 网络参数
|
||
wifiSSIDPrefix: string; // WiFi SSID前缀
|
||
};
|
||
};
|
||
|
||
signature: { // 数字签名
|
||
algorithm: string; // 签名算法
|
||
value: string; // 签名值
|
||
publicKey: string; // 公钥(用于验证)
|
||
};
|
||
}
|
||
```
|
||
|
||
## 数据库表结构
|
||
|
||
### licenses 表(已扩展)
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| id | INTEGER | 主键 |
|
||
| model | TEXT | 设备型号 |
|
||
| modules | TEXT | 授权模块(逗号分隔) |
|
||
| expiry | TEXT | 到期时间 |
|
||
| status | TEXT | 状态:"生效"或"已停用" |
|
||
| config_id | INTEGER | 关联的配置文件ID |
|
||
| device_sn | TEXT | 设备SN(可选,用于设备级授权) |
|
||
| license_file | TEXT | 生成的JSON授权文件 |
|
||
| created_at | TEXT | 创建时间 |
|
||
| updated_at | TEXT | 更新时间 |
|
||
|
||
### license_download_logs 表(新增)
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| id | INTEGER | 主键 |
|
||
| license_id | INTEGER | 关联的授权ID |
|
||
| device_sn | TEXT | 下载的设备SN |
|
||
| download_time | TEXT | 下载时间 |
|
||
| ip_address | TEXT | 客户端IP |
|
||
| app_version | TEXT | APP版本信息 |
|
||
|
||
## 使用流程
|
||
|
||
### 管理员操作流程
|
||
|
||
1. **创建配置文件** - 在"配置文件管理"页面为设备型号创建配置
|
||
2. **创建授权** - 在"授权管理"页面选择设备型号、授权项和配置
|
||
3. **系统自动生成** - 保存时自动生成JSON授权文件并存储
|
||
|
||
### 手机APP使用流程
|
||
|
||
1. APP启动时调用 `GET /api/licenses/download?sn={device_sn}`
|
||
2. 平台返回JSON格式的授权文件
|
||
3. APP解析授权文件,启用对应功能模块
|
||
4. APP可以验证签名确保文件完整性
|
||
|
||
## 安全特性
|
||
|
||
1. **数字签名** - 每个授权文件都包含SHA256签名
|
||
2. **下载日志** - 记录每次授权的下载行为
|
||
3. **有效期控制** - 只返回未过期的有效授权
|
||
4. **双重匹配** - 支持设备级和型号级授权
|
||
|
||
## 测试示例
|
||
|
||
### 使用curl测试下载接口
|
||
|
||
```bash
|
||
# 获取设备SN为 GD30-20260430-001 的授权文件
|
||
curl "http://localhost:3000/api/licenses/download?sn=GD30-20260430-001"
|
||
```
|
||
|
||
### JavaScript调用示例
|
||
|
||
```javascript
|
||
async function getLicense(deviceSN) {
|
||
const response = await fetch(`/api/licenses/download?sn=${deviceSN}`);
|
||
|
||
if (!response.ok) {
|
||
const error = await response.json();
|
||
throw new Error(error.error || '获取授权失败');
|
||
}
|
||
|
||
const license = await response.json();
|
||
|
||
// 验证签名
|
||
const isValid = verifySignature(license);
|
||
if (!isValid) {
|
||
throw new Error('授权文件签名验证失败');
|
||
}
|
||
|
||
return license;
|
||
}
|
||
|
||
function verifySignature(license) {
|
||
const { signature, ...dataWithoutSig } = license;
|
||
const jsonString = JSON.stringify(dataWithoutSig, null, 2);
|
||
const calculatedHash = sha256(jsonString);
|
||
return calculatedHash === signature.value;
|
||
}
|
||
```
|
||
|
||
## 注意事项
|
||
|
||
1. 授权文件一旦生成,建议不要频繁修改,以保持稳定性
|
||
2. 设备级授权优先级高于型号级授权
|
||
3. 签名验证应在APP端实现,确保文件未被篡改
|
||
4. 定期清理过期的下载日志以优化性能 |