8.9 KiB
8.9 KiB
授权文件管理 API 文档
概述
本系统提供基于设备型号和配置文件的授权文件生成功能。手机APP可以通过设备SN号从平台获取对应的授权文件(JSON格式)。
核心功能
- 授权项管理 - 定义设备可用的功能模块
- 配置文件管理 - 设备的技术参数配置
- 授权文件生成 - 根据授权项+配置自动生成JSON授权文件
- 授权文件下载 - 手机APP通过设备SN获取授权文件
API 接口
1. 获取授权列表
接口: GET /api/licenses
响应示例:
[
{
"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
请求体:
{
"model": "GD-30",
"modules": "一维自电/电阻率/激电测试模块, 二维自电/电阻率/激电测试模块, 三维自电/电阻率/激电测试模块",
"expiry": "2027-04-30",
"status": "生效",
"config_id": 5,
"device_sn": ""
}
参数说明:
model: 设备型号(必填)modules: 授权模块列表,多个模块用", "分隔(必填)expiry: 到期时间(可选)status: 状态,"生效"或"已停用"(可选,默认"生效")config_id: 配置文件ID(可选,不传则自动使用最新配置)device_sn: 设备SN(可选,用于设备级授权,不填则为型号级授权)
响应示例:
{
"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
请求体:
{
"id": 1,
"model": "GD-30",
"modules": "一维自电/电阻率/激电测试模块, 二维自电/电阻率/激电测试模块",
"expiry": "2027-04-30",
"status": "生效",
"config_id": 5,
"device_sn": ""
}
响应示例:
{
"ok": true
}
4. 手机APP获取授权文件 ⭐
接口: GET /api/licenses/download?sn={device_sn}
说明: 这是手机APP调用的核心接口,根据设备SN号返回对应的授权文件JSON。
查询参数:
sn: 设备序列号(必填)
响应示例:
{
"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"
}
}
错误响应:
// 设备不存在
{
"error": "设备不存在"
}
// 无有效授权
{
"error": "该设备暂无有效授权",
"deviceSN": "GD30-20260430-001",
"deviceModel": "GD-30 Supreme"
}
查找逻辑:
- 优先查找绑定到具体设备SN的授权(device_sn字段匹配)
- 如果没有设备级授权,则查找型号级别的授权(model字段匹配)
- 只返回状态为"生效"且未过期的授权
- 每次下载都会记录下载日志
5. 预览授权文件
接口: GET /api/licenses/{id}/preview
说明: 在管理后台预览授权文件的JSON内容。
路径参数:
id: 授权ID
响应: 与下载接口相同的JSON格式
授权文件JSON结构说明
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版本信息 |
使用流程
管理员操作流程
- 创建配置文件 - 在"配置文件管理"页面为设备型号创建配置
- 创建授权 - 在"授权管理"页面选择设备型号、授权项和配置
- 系统自动生成 - 保存时自动生成JSON授权文件并存储
手机APP使用流程
- APP启动时调用
GET /api/licenses/download?sn={device_sn} - 平台返回JSON格式的授权文件
- APP解析授权文件,启用对应功能模块
- APP可以验证签名确保文件完整性
安全特性
- 数字签名 - 每个授权文件都包含SHA256签名
- 下载日志 - 记录每次授权的下载行为
- 有效期控制 - 只返回未过期的有效授权
- 双重匹配 - 支持设备级和型号级授权
测试示例
使用curl测试下载接口
# 获取设备SN为 GD30-20260430-001 的授权文件
curl "http://localhost:3000/api/licenses/download?sn=GD30-20260430-001"
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;
}
注意事项
- 授权文件一旦生成,建议不要频繁修改,以保持稳定性
- 设备级授权优先级高于型号级授权
- 签名验证应在APP端实现,确保文件未被篡改
- 定期清理过期的下载日志以优化性能