# 授权文件管理 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. 定期清理过期的下载日志以优化性能